Compare commits

5 Commits

13 changed files with 967 additions and 284 deletions

View File

@@ -1,217 +1,239 @@
#include "Camera.hpp" #include "Camera.hpp"
#include "elements/Transformable.hpp" #include "elements/Transformable.hpp"
#include "interfaces/IRenderer.hpp" #include "interfaces/IRenderer.hpp"
#include "uuid.h" #include "uuid.h"
TSE::Camera* TSE::Camera::mainCamera = nullptr; TSE::Camera* TSE::Camera::mainCamera = nullptr;
TSE::ICameraHelper* TSE::Camera::helper = nullptr; TSE::ICameraHelper* TSE::Camera::helper = nullptr;
float TSE::Camera::GetRenderScale() const float TSE::Camera::GetRenderScale() const
{ {
return RenderScale; return RenderScale;
} }
TSE::ProjectionType TSE::Camera::GetProjection() const TSE::ProjectionType TSE::Camera::GetProjection() const
{ {
return projection; return projection;
} }
float TSE::Camera::GetNearClippingPlane() const float TSE::Camera::GetNearClippingPlane() const
{ {
return nearClippingPlane; return nearClippingPlane;
} }
float TSE::Camera::GetFarClippingPlane() const float TSE::Camera::GetFarClippingPlane() const
{ {
return farClippingPlane; return farClippingPlane;
} }
float TSE::Camera::GetFov() const float TSE::Camera::GetFov() const
{ {
return fov; return fov;
} }
const TSE::Vector2 &TSE::Camera::GetRenderTargetSize() const const TSE::Vector2 &TSE::Camera::GetRenderTargetSize() const
{ {
return lastRtSize; return lastRtSize;
} }
TSE::Vector3 TSE::Camera::SceenPositionToGamePosition(Vector2 screenPos) TSE::Vector3 TSE::Camera::SceenPositionToGamePosition(Vector2 screenPos)
{ {
float x = 2.0f * screenPos.x / lastRtSize.x -1.0f; float x = 2.0f * screenPos.x / lastRtSize.x -1.0f;
float y = 1.0f - 2.0f * screenPos.y / lastRtSize.y; float y = 1.0f - 2.0f * screenPos.y / lastRtSize.y;
float z = -1.0f; float z = -1.0f;
Vector4 ndc(x,y,x,1); Vector4 ndc(x,y,x,1);
Matrix4x4 InversProj = Matrix4x4(*projectionMatrix); Matrix4x4 InversProj = Matrix4x4(*projectionMatrix);
InversProj.Invert(); InversProj.Invert();
Vector4 camSpace = InversProj * ndc; Vector4 camSpace = InversProj * ndc;
camSpace = camSpace / camSpace.w; camSpace = camSpace / camSpace.w;
Vector3 relativPos(camSpace); Vector3 relativPos(camSpace);
relativPos.z = 0; relativPos.z = 0;
return baseObject->LocalToGlobalPosition(relativPos); return baseObject->LocalToGlobalPosition(relativPos);
} }
void TSE::Camera::SetRenderScale(float v) void TSE::Camera::SetRenderScale(float v)
{ {
RenderScale = v; RecalculateProjMatrix(); RenderScale = v; RecalculateProjMatrix();
} }
void TSE::Camera::SetProjection(ProjectionType v) void TSE::Camera::SetProjection(ProjectionType v)
{ {
projection = v; RecalculateProjMatrix(); projection = v; RecalculateProjMatrix();
} }
void TSE::Camera::SetNearClippingPlane(float v) void TSE::Camera::SetNearClippingPlane(float v)
{ {
nearClippingPlane = v; RecalculateProjMatrix(); nearClippingPlane = v; RecalculateProjMatrix();
} }
void TSE::Camera::SetFarClippingPlane(float v) void TSE::Camera::SetFarClippingPlane(float v)
{ {
farClippingPlane = v; RecalculateProjMatrix(); farClippingPlane = v; RecalculateProjMatrix();
} }
void TSE::Camera::SetFov(float v) void TSE::Camera::SetFov(float v)
{ {
fov = v; RecalculateProjMatrix(); fov = v; RecalculateProjMatrix();
} }
TSE::Camera::Camera() TSE::Camera::Camera()
{ {
} }
TSE::Camera::~Camera() TSE::Camera::~Camera()
{ {
delete(projectionMatrix); delete(projectionMatrix);
if(mainCamera == this) if(mainCamera == this)
mainCamera = nullptr; mainCamera = nullptr;
} }
void TSE::Camera::OnResize(float width, float height, IResizable *wnd) void TSE::Camera::OnResize(float width, float height, IResizable *wnd)
{ {
lastRtSize = {width, height}; lastRtSize = {width, height};
RecalculateProjMatrix(); RecalculateProjMatrix();
} }
void TSE::Camera::SetRenderTarget(IRenderTarget *target) void TSE::Camera::SetRenderTarget(IRenderTarget *target)
{ {
if(rt != nullptr) if(rt != nullptr)
rt->RemoveResizeNotifiable(this); rt->RemoveResizeNotifiable(this);
if(target != nullptr) if(target != nullptr)
target->AddResizeNotifiable(this); target->AddResizeNotifiable(this);
rt = target; rt = target;
if(lastRtSize != rt->GetRawIResizableSize()) if(lastRtSize != rt->GetRawIResizableSize())
{ {
lastRtSize = rt->GetRawIResizableSize(); lastRtSize = rt->GetRawIResizableSize();
RecalculateProjMatrix(); RecalculateProjMatrix();
} }
} }
TSE::IRenderTarget *TSE::Camera::GetRenderTarget() TSE::IRenderTarget *TSE::Camera::GetRenderTarget()
{ {
return rt; return rt;
} }
void TSE::Camera::RecalculateProjMatrix() void TSE::Camera::RecalculateProjMatrix()
{ {
if(projectionMatrix) if(projectionMatrix)
delete(projectionMatrix); delete(projectionMatrix);
if(projection == ProjectionType::Orthographic) if(projection == ProjectionType::Orthographic)
{ {
float x = lastRtSize.x / RenderScale; float x = lastRtSize.x / RenderScale;
float y = lastRtSize.y / RenderScale; float y = lastRtSize.y / RenderScale;
float mx = -x; float mx = -x;
float my = -y; float my = -y;
projectionMatrix = new Matrix4x4(Matrix4x4::Orthographic(mx, x, my, y, nearClippingPlane, farClippingPlane)); projectionMatrix = new Matrix4x4(Matrix4x4::Orthographic(mx, x, my, y, nearClippingPlane, farClippingPlane));
} }
else if(projection == ProjectionType::Perspective) else if(projection == ProjectionType::Perspective)
{ {
float x = lastRtSize.x / RenderScale; float x = lastRtSize.x / RenderScale;
float y = lastRtSize.y / RenderScale; float y = lastRtSize.y / RenderScale;
float aspectRatio = x / y; float aspectRatio = x / y;
projectionMatrix = new Matrix4x4(Matrix4x4::Perspective(fov, aspectRatio, nearClippingPlane, farClippingPlane)); projectionMatrix = new Matrix4x4(Matrix4x4::Perspective(fov, aspectRatio, nearClippingPlane, farClippingPlane));
} }
} }
void TSE::Camera::OnUpdate() void TSE::Camera::OnUpdate()
{ {
if(mainCamera == nullptr && baseObject->name != ".EditorCamera") if(mainCamera == nullptr && baseObject->name != ".EditorCamera")
{ {
mainCamera = this; mainCamera = this;
} }
if(rt != nullptr) if(rt != nullptr)
IRenderer::camerasToRenderWith.push_back(this); IRenderer::camerasToRenderWith.push_back(this);
} }
void TSE::Camera::Start() void TSE::Camera::Start()
{ {
if(mainCamera == nullptr && baseObject->name != ".EditorCamera") if(mainCamera == nullptr && baseObject->name != ".EditorCamera")
{ {
mainCamera = this; mainCamera = this;
} }
} }
TSE::Matrix4x4 BuildView_Zplus_RH(const TSE::Matrix4x4& world) TSE::Matrix4x4 BuildView_Zplus_RH(const TSE::Matrix4x4& world)
{ {
using namespace TSE; using namespace TSE;
// Welt-Position (w=1) // Welt-Position (w=1)
Vector3 pos = Vector3(world * Vector4(0,0,0,1)); Vector3 pos = Vector3(world * Vector4(0,0,0,1));
// Richtungsachsen in Welt (w=0, KEINE Translation!) // Richtungsachsen in Welt (w=0, KEINE Translation!)
Vector3 fwdWS = Vector3(world * Vector4(0,0,1,0)); // +Z vorwärts in Welt Vector3 fwdWS = Vector3(world * Vector4(0,0,1,0)); // +Z vorwärts in Welt
Vector3 upWS = Vector3(world * Vector4(0,1,0,0)); // +Y oben in Welt Vector3 upWS = Vector3(world * Vector4(0,1,0,0)); // +Y oben in Welt
// Orthonormale Basis aufbauen (X+ soll "right" sein) // Orthonormale Basis aufbauen (X+ soll "right" sein)
Vector3 f = Vector3::Normalize(fwdWS); Vector3 f = Vector3::Normalize(fwdWS);
Vector3 r = Vector3::Normalize(Vector3::Cross(upWS, f)); // right = up × forward => (+1,0,0) im Identity-Fall Vector3 r = Vector3::Normalize(Vector3::Cross(upWS, f)); // right = up × forward => (+1,0,0) im Identity-Fall
Vector3 u = Vector3::Cross(f, r); // re-orthonormalisiertes up Vector3 u = Vector3::Cross(f, r); // re-orthonormalisiertes up
Matrix4x4 view(1.0f); // Identität als Basis Matrix4x4 view(1.0f); // Identität als Basis
// Row-major befüllen (Zeilen = r,u,-f), letzte Spalte = -dot(row, pos) bzw. +dot(f,pos) // Row-major befüllen (Zeilen = r,u,-f), letzte Spalte = -dot(row, pos) bzw. +dot(f,pos)
view.m[0][0] = r.x; view.m[0][1] = r.y; view.m[0][2] = r.z; view.m[0][3] = -Vector3::Dot(r, pos); view.m[0][0] = r.x; view.m[0][1] = r.y; view.m[0][2] = r.z; view.m[0][3] = -Vector3::Dot(r, pos);
view.m[1][0] = u.x; view.m[1][1] = u.y; view.m[1][2] = u.z; view.m[1][3] = -Vector3::Dot(u, pos); view.m[1][0] = u.x; view.m[1][1] = u.y; view.m[1][2] = u.z; view.m[1][3] = -Vector3::Dot(u, pos);
view.m[2][0] = -f.x; view.m[2][1] = -f.y; view.m[2][2] = -f.z; view.m[2][3] = Vector3::Dot(f, pos); view.m[2][0] = -f.x; view.m[2][1] = -f.y; view.m[2][2] = -f.z; view.m[2][3] = Vector3::Dot(f, pos);
view.m[3][0] = 0.0f; view.m[3][1] = 0.0f; view.m[3][2] = 0.0f; view.m[3][3] = 1.0f; view.m[3][0] = 0.0f; view.m[3][1] = 0.0f; view.m[3][2] = 0.0f; view.m[3][3] = 1.0f;
return view; return view;
} }
void TSE::Camera::PreDraw(IShader *shader) void TSE::Camera::PreDraw(IShader *shader)
{ {
rt->Bind(); rt->Bind();
shader->SetUniform("prMatrix", projectionMatrix); // shader->SetUniform("prMatrix", projectionMatrix);
auto worlmatrix = baseObject->GetGlobalMatrix(); // auto worlmatrix = baseObject->GetGlobalMatrix();
viewMatrix = BuildView_Zplus_RH(worlmatrix); // viewMatrix = BuildView_Zplus_RH(worlmatrix);
shader->SetUniform("camMatrix", &viewMatrix); // shader->SetUniform("camMatrix", &viewMatrix);
helper->OnRenderTargetChanged(lastRtSize.x, lastRtSize.y); // helper->OnRenderTargetChanged(lastRtSize.x, lastRtSize.y);
}
Vector3 pos = baseObject->GetGlobalPosition();
void TSE::Camera::PostDraw() Vector3 right = baseObject->LocalToGlobalPosition(Vector3::right) - pos;
{ Vector3 up = baseObject->LocalToGlobalPosition(Vector3::up) - pos;
rt->Unbind(); Vector3 forward = baseObject->LocalToGlobalPosition(Vector3::forward) - pos;
} forward.Normalize();
void TSE::Camera::Bind() shader->SetUniform("CamPos", &pos);
{ shader->SetUniform("CamRight", &right);
rt->Bind(); shader->SetUniform("CamUp", &up);
} shader->SetUniform("CamForward", &forward);
void TSE::Camera::Unbind() float x = lastRtSize.x / RenderScale;
{ float y = lastRtSize.y / RenderScale;
rt->Unbind(); float mx = -x;
} float my = -y;
shader->SetUniform("OrthoLeft", mx);
void TSE::Camera::UpdateRenderTarget() shader->SetUniform("OrthoRight", x);
{ shader->SetUniform("OrthoBottom", my);
rt->Update(); shader->SetUniform("OrthoTop", y);
} shader->SetUniform("NearPlane", nearClippingPlane);
shader->SetUniform("FarPlane", farClippingPlane);
}
void TSE::Camera::PostDraw()
{
rt->Unbind();
}
void TSE::Camera::Bind()
{
rt->Bind();
}
void TSE::Camera::Unbind()
{
rt->Unbind();
}
void TSE::Camera::UpdateRenderTarget()
{
rt->Update();
}

View File

@@ -1,6 +1,7 @@
#include "OrdererSpriteSet.hpp" #include "OrdererSpriteSet.hpp"
#include <algorithm> #include <algorithm>
#include <tuple> #include <tuple>
#include "Debug.hpp"
TSE::OrdererSpriteSetChunk::OrdererSpriteSetChunk(int _chunksize, const Vector2 &_pos, SortingOrder _order) TSE::OrdererSpriteSetChunk::OrdererSpriteSetChunk(int _chunksize, const Vector2 &_pos, SortingOrder _order)
{ {
@@ -144,6 +145,8 @@ void TSE::OrdererSpriteSet::SetSprite(Vector2 p, Vector2 Spriteindex, float heig
{ {
Vector2 chunkInnerPos = LocalToChunkPos(p); Vector2 chunkInnerPos = LocalToChunkPos(p);
Vector2 chunkIndex = p - chunkInnerPos; Vector2 chunkIndex = p - chunkInnerPos;
// Vector2 p2 = Vector2((int)p.x % chunkSize, (int)p.y % chunkSize);
// Vector2 chunkIndex = p - p2;
if(!chunks.contains(chunkIndex)) if(!chunks.contains(chunkIndex))
{ {
dirty = true; dirty = true;
@@ -175,7 +178,9 @@ const std::vector<TSE::Vector2> *TSE::OrdererSpriteSet::GetChunkPositionsInOrder
case TopLeft: case TopLeft:
std::sort(orderedChunks.begin(), orderedChunks.end(), [](const Vector2& a, const Vector2& b) std::sort(orderedChunks.begin(), orderedChunks.end(), [](const Vector2& a, const Vector2& b)
{ {
return std::tie(a.y, a.x) > std::tie(b.y, b.x); if (a.y != b.y)
return a.y > b.y;
return a.x < b.x;
}); });
break; break;
case TopRight: case TopRight:
@@ -189,7 +194,9 @@ const std::vector<TSE::Vector2> *TSE::OrdererSpriteSet::GetChunkPositionsInOrder
case BottomLeft: case BottomLeft:
std::sort(orderedChunks.begin(), orderedChunks.end(), [](const Vector2& a, const Vector2& b) std::sort(orderedChunks.begin(), orderedChunks.end(), [](const Vector2& a, const Vector2& b)
{ {
return std::tie(a.y, a.x) < std::tie(b.y, b.x); if (a.y != b.y)
return a.y < b.y;
return a.x < b.x;
}); });
break; break;
case BottomRight: case BottomRight:
@@ -203,6 +210,14 @@ const std::vector<TSE::Vector2> *TSE::OrdererSpriteSet::GetChunkPositionsInOrder
} }
dirty = false; dirty = false;
string poses = "[";
for(auto pos : orderedChunks)
{
poses += pos.ToString() + ",";
}
poses.erase(poses.end() - 1);
poses += "]";
TSE_LOG("orderedPositions: " + poses);
} }
return &orderedChunks; return &orderedChunks;
} }

View File

@@ -23,7 +23,6 @@ namespace TSE
public: public:
string name = "Unnamed"; string name = "Unnamed";
inline static ITextureHelper* helper = nullptr;
Texture(const string& path); Texture(const string& path);
Texture(const int& width, const int& height, int bpp = 32); Texture(const int& width, const int& height, int bpp = 32);

View File

@@ -0,0 +1,429 @@
#include "VolumeTexture3D.hpp"
#include "Debug.hpp"
#include <algorithm>
#include <cctype>
#include <filesystem>
#include <vector>
TSE::VolumeTexture3D::VolumeTexture3D(const string &path)
{
namespace fs = std::filesystem;
Size = Vector3(0, 0, 0);
Bpp = 0;
std::error_code ec;
const fs::path folderPath = fs::absolute(path, ec);
if(ec || !fs::exists(folderPath, ec))
{
TSE_WARNING("Can't create VolumeTexture3D because the given path is inaccessible: \n" + path);
return;
}
if(ec || !fs::is_directory(folderPath, ec))
{
TSE_WARNING("Can't create VolumeTexture3D because the given path is not a folder: \n" + folderPath.string());
return;
}
std::vector<fs::path> pngFiles;
for(fs::directory_iterator it(folderPath, ec); !ec && it != fs::directory_iterator(); it.increment(ec))
{
if(!it->is_regular_file(ec))
continue;
const fs::path &filePath = it->path();
auto extension = filePath.extension().string();
std::transform(extension.begin(), extension.end(), extension.begin(), [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
if(extension == ".png")
pngFiles.push_back(filePath);
}
if(ec)
{
TSE_WARNING("Can't read VolumeTexture3D folder: \n" + folderPath.string());
return;
}
if(pngFiles.empty())
{
TSE_WARNING("Can't create VolumeTexture3D because the folder contains no png files: \n" + folderPath.string());
return;
}
std::sort(pngFiles.begin(), pngFiles.end());
std::vector<FIBITMAP*> loadedBitmaps;
loadedBitmaps.reserve(pngFiles.size());
uint width = 0;
uint height = 0;
for(const fs::path &filePath : pngFiles)
{
FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(filePath.string().c_str(), 0);
if(fif == FREE_IMAGE_FORMAT::FIF_UNKNOWN)
fif = FreeImage_GetFIFFromFilename(filePath.string().c_str());
if(fif == FREE_IMAGE_FORMAT::FIF_UNKNOWN || !FreeImage_FIFSupportsReading(fif))
{
TSE_WARNING("Failed to load png for VolumeTexture3D: \n" + filePath.string());
for(FIBITMAP* loadedBmp : loadedBitmaps)
FreeImage_Unload(loadedBmp);
return;
}
FIBITMAP* currentBmp = FreeImage_Load(fif, filePath.string().c_str());
if(currentBmp == nullptr)
{
TSE_WARNING("Failed to load png for VolumeTexture3D: \n" + filePath.string());
for(FIBITMAP* loadedBmp : loadedBitmaps)
FreeImage_Unload(loadedBmp);
return;
}
if(FreeImage_GetBPP(currentBmp) != 32)
{
FIBITMAP* convertedBmp = FreeImage_ConvertTo32Bits(currentBmp);
FreeImage_Unload(currentBmp);
currentBmp = convertedBmp;
}
if(currentBmp == nullptr)
{
TSE_WARNING("Failed to convert png for VolumeTexture3D: \n" + filePath.string());
for(FIBITMAP* loadedBmp : loadedBitmaps)
FreeImage_Unload(loadedBmp);
return;
}
const uint currentWidth = FreeImage_GetWidth(currentBmp);
const uint currentHeight = FreeImage_GetHeight(currentBmp);
if(loadedBitmaps.empty())
{
width = currentWidth;
height = currentHeight;
}
else if(currentWidth != width || currentHeight != height)
{
TSE_WARNING("Can't create VolumeTexture3D because all pngs must have the same dimensions: \n" + filePath.string());
FreeImage_Unload(currentBmp);
for(FIBITMAP* loadedBmp : loadedBitmaps)
FreeImage_Unload(loadedBmp);
return;
}
loadedBitmaps.push_back(currentBmp);
}
Bpp = 32;
chanels = 4;
Size = Vector3(width, height, static_cast<float>(loadedBitmaps.size()));
bmp = new FIBITMAP*[loadedBitmaps.size()];
imagePtr = new byte*[loadedBitmaps.size()];
for(size_t i = 0; i < loadedBitmaps.size(); ++i)
{
bmp[i] = loadedBitmaps[i];
imagePtr[i] = FreeImage_GetBits(bmp[i]);
}
regist();
}
TSE::VolumeTexture3D::VolumeTexture3D(const int &width, const int &height, const int &depth, int bpp)
{
switch (bpp)
{
case 32:
chanels = 4;
break;
case 24:
chanels = 3;
case 16:
chanels = 1;
case 8:
chanels = 4;
}
Bpp = bpp;
Size = Vector3(width, height, depth);
bmp = new FIBITMAP*[depth];
imagePtr = new byte*[depth];
for(int i = 0; i < Depth(); i++)
{
bmp[i] = FreeImage_Allocate(width, height, bpp);
imagePtr[i] = FreeImage_GetBits(bmp[i]);
}
regist();
}
TSE::VolumeTexture3D::VolumeTexture3D(const Vector3 &size, int bpp)
: VolumeTexture3D(size.x, size.y, size.z, bpp) { }
TSE::VolumeTexture3D::~VolumeTexture3D()
{
if(bmp != nullptr)
{
for(int i = 0; i < Depth(); i++)
{
if(bmp[i] != nullptr)
{
FreeImage_Unload(bmp[i]);
bmp[i] = nullptr;
}
}
delete [] bmp;
delete [] imagePtr;
}
if(TextureID != 0)
{
PlatformDestroy();
TextureID = 0;
}
}
TSE::uint TSE::VolumeTexture3D::bpp() const
{
return Bpp;
}
TSE::Vector2 TSE::VolumeTexture3D::size() const
{
return Vector2(Size.x, Size.y);
}
float TSE::VolumeTexture3D::Width() const
{
return Size.x;
}
float TSE::VolumeTexture3D::Height() const
{
return Size.y;
}
float TSE::VolumeTexture3D::Depth() const
{
return Size.z;
}
TSE::byte TSE::VolumeTexture3D::Chanels() const
{
return chanels;
}
TSE::byte *TSE::VolumeTexture3D::GetImagePtr(const int depth) const
{
return imagePtr[depth];
}
void TSE::VolumeTexture3D::SetPixel(const Vector3 &pos, const Color &c)
{
SetPixel(pos.x, pos.y, pos.z, c);
}
void TSE::VolumeTexture3D::GetPixel(const Vector3 &pos, Color &c) const
{
GetPixel(pos.x, pos.y, pos.z, c);
}
void TSE::VolumeTexture3D::SetPixelNoApply(const Vector3 &pos, const Color &c)
{
SetPixelNoApply(pos.x, pos.y, pos.z, c);
}
void TSE::VolumeTexture3D::SetChanels(const byte &ch)
{
chanels = ch;
}
TSE::uint TSE::VolumeTexture3D::GetTextureId() const
{
return TextureID;
}
void TSE::VolumeTexture3D::SetTextureId(uint id)
{
TextureID = id;
}
void TSE::VolumeTexture3D::SetPixel(const int &x, const int &y, const int &z, const Color &c)
{
SetPixelNoApply(x,y,z,c);
Apply();
}
void TSE::VolumeTexture3D::GetPixel(const int &x, const int &y, const int &z, Color &c) const
{
if(x >= Width() || x < 0 || y >= Height() || y < 0|| z >= Depth() || z < 0)
{
TSE_WARNING("trying to access pixel outside of texture.\n pixel: (" + std::to_string(x) + ";" + std::to_string(y) + ";" + std::to_string(z) + ")\nTexture size: (" + std::to_string(Width()) + ";" + std::to_string(Height()) + ";" + std::to_string(Depth()) );
return;
}
byte* pixel = getPixelPointer(x,y,z);
byte b = *pixel++;
byte g = *pixel++;
byte r = *pixel++;
byte a = *pixel++;
if(bpp() == 8)
c = Color(r,r,r);
else if(bpp() == 24)
c = Color(r,g,b,a);
else if(bpp() == 32)
c = Color(r,g,b);
}
void TSE::VolumeTexture3D::Fill(const Color &c)
{
for (int x = 0; x < Width(); x++)
{
for (int y = 0; y < Height(); y++)
{
for (int z = 0; z < Depth(); z++)
{
SetPixelNoApply(x,y,z,c);
}
}
}
Apply();
}
void TSE::VolumeTexture3D::SetPixelNoApply(const int &x, const int &y, const int &z, const Color &c)
{
if(x >= Width() || x < 0 || y >= Height() || y < 0 || z >= Depth() || z < 0)
{
TSE_WARNING("trying to access pixel outside of texture.\n pixel: (" + std::to_string(x) + ";" + std::to_string(y) + ";" + std::to_string(z) + ")\nTexture size: (" + std::to_string(Width()) + ";" + std::to_string(Height()) + ";" + std::to_string(Depth()) );
return;
}
byte* pixel = getPixelPointer(x,y,z);
if(chanels == 4 && bpp() == 8)
{
byte r2bit = static_cast<byte>(c.r * 3.0f);
byte g2bit = static_cast<byte>(c.g * 3.0f);
byte b2bit = static_cast<byte>(c.b * 3.0f);
byte a2bit = static_cast<byte>(c.a * 3.0f);
byte result = (r2bit << 6) | (g2bit << 4) | (b2bit << 2) | a2bit;
*pixel++ = result;
return;
}
*pixel++ = c.B();
if(bpp() > 8)
{
*pixel++ = c.G();
*pixel++ = c.R();
if(bpp() > 24)
*pixel++ = c.A();
}
}
void TSE::VolumeTexture3D::AddPixelNoApply(const int &x, const int &y, const int &z, const Color &c)
{
if(x >= Width() || x < 0 ||y >= Height() || y < 0 || z >= Depth() || z < 0)
{
TSE_WARNING("trying to access pixel outside of texture.\n pixel: (" + std::to_string(x) + ";" + std::to_string(y) + ";" + std::to_string(z) + ")\nTexture size: (" + std::to_string(Width()) + ";" + std::to_string(Height()) + ";" + std::to_string(Depth()) );
return;
}
byte* pixel = getPixelPointer(x,y,z);
if(chanels == 4 && bpp() == 8) //TODO add propper adding, becouse currently is only setting
{
byte r2bit = static_cast<byte>(c.r * 3.0f);
byte g2bit = static_cast<byte>(c.g * 3.0f);
byte b2bit = static_cast<byte>(c.b * 3.0f);
byte a2bit = static_cast<byte>(c.a * 3.0f);
byte result = (r2bit << 6) | (g2bit << 4) | (b2bit << 2) | a2bit;
*pixel++ = result;
return;
}
Color bc(pixel[2], pixel[1], pixel[0], pixel[3]);
bc = c + bc;
*pixel++ = bc.B();
if(bpp() > 8)
{
*pixel++ = bc.G();
*pixel++ = bc.R();
if(bpp() > 24)
*pixel++ = bc.A();
}
}
void TSE::VolumeTexture3D::Recreate(const int &x, const int &y, const int &z, const int &bpp, const int &chanels)
{
if(bmp != nullptr)
{
for(int i = 0; i < Depth(); i++)
{
if(bmp[i] != nullptr)
{
FreeImage_Unload(bmp[i]);
bmp[i] = nullptr;
}
}
delete [] bmp;
delete [] imagePtr;
}
if(TextureID != 0)
{
PlatformDestroy();
TextureID = 0;
}
this->chanels = chanels;
Bpp = bpp;
Size = Vector3(x, y, z);
bmp = new FIBITMAP*[z];
imagePtr = new byte*[z];
for(int i = 0; i < Depth(); i++)
{
bmp[i] = FreeImage_Allocate(x, y, bpp);
imagePtr[i] = FreeImage_GetBits(bmp[i]);
}
regist();
}
void TSE::VolumeTexture3D::SavePNG(const std::string &path) const
{
//TODO: implement save all images as PNG in the given path, if the given path is inaccaseable, or not a folder, ust TSE_WARNING with an apropriate message
}
TSE::byte *TSE::VolumeTexture3D::getPixelPointer(const int &x, const int &y, const int &z) const
{
int alphaoffset = y * 2;
if(bpp() > 24)
alphaoffset = 0;
int offset = ((y * Width() + x) * (bpp() / 8) + alphaoffset);
return imagePtr[z] + offset;
}
void TSE::VolumeTexture3D::bind() const
{
helper->Bind3D(this);
}
void TSE::VolumeTexture3D::unbind() const
{
helper->UnBind3D(this);
}
void TSE::VolumeTexture3D::Apply()
{
helper->Apply3D(this);
}
void TSE::VolumeTexture3D::regist()
{
helper->Regist3D(this);
}
void TSE::VolumeTexture3D::PlatformDestroy()
{
helper->PlatromDestroy3D(this);
}

View File

@@ -0,0 +1,61 @@
#pragma once
#include "interfaces/ITexture.hpp"
#include "Types.hpp"
#include "Vector3.hpp"
#include "Color.hpp"
#include "interfaces/ITextureHelper.hpp"
#define FREEIMAGE_LIB
#include "FI/FreeImage.h"
namespace TSE
{
class VolumeTexture3D : public ITexture
{
protected:
uint TextureID = 0;
Vector3 Size;
uint Bpp;
byte chanels = 0;
FIBITMAP** bmp = nullptr;
byte** imagePtr = nullptr;
public:
string name = "Unnamed";
VolumeTexture3D(const string& path);
VolumeTexture3D(const int& width, const int& height, const int& depth, int bpp = 32);
VolumeTexture3D(const Vector3& size, int bpp = 32);
~VolumeTexture3D();
uint bpp() const;
Vector2 size() const override;
float Width() const override;
float Height() const override;
float Depth() const;
byte Chanels() const;
byte* GetImagePtr(const int depth) const;
void SetPixel(const Vector3& pos, const Color& c);
void GetPixel(const Vector3& pos, Color& c) const;
void SetPixelNoApply(const Vector3& pos, const Color& c);
void SetChanels(const byte& ch);
uint GetTextureId() const override;
void SetTextureId(uint id);
void SetPixel(const int& x, const int& y, const int& z, const Color& c);
void GetPixel(const int& x, const int& y, const int& z, Color& c) const;
void Fill(const Color& c);
void SetPixelNoApply(const int& x, const int& y, const int& z, const Color& c);
void AddPixelNoApply(const int& x, const int& y, const int& z, const Color& c);
void Recreate(const int& x, const int& y, const int& z, const int& bpp, const int& chanels);
void SavePNG(const std::string& path) const;
byte* getPixelPointer(const int& x, const int& y, const int& z) const;
void bind() const;
void unbind() const;
void Apply();
void regist();
void PlatformDestroy();
};
} // namespace TSE

View File

@@ -1,12 +1,15 @@
#pragma once #pragma once
#include "Vector2.hpp" #include "Vector2.hpp"
#include "interfaces/ITextureHelper.hpp"
namespace TSE namespace TSE
{ {
class ITexture class ITexture
{ {
public: public:
inline static ITextureHelper* helper = nullptr;
virtual ~ITexture() = default; virtual ~ITexture() = default;
virtual Vector2 size() const = 0; virtual Vector2 size() const = 0;
virtual float Width() const = 0; virtual float Width() const = 0;

View File

@@ -3,6 +3,7 @@
namespace TSE namespace TSE
{ {
class Texture; class Texture;
class VolumeTexture3D;
class ITextureHelper class ITextureHelper
{ {
@@ -12,5 +13,11 @@ namespace TSE
virtual void Apply(Texture* tex) = 0; virtual void Apply(Texture* tex) = 0;
virtual void Regist(Texture* tex) = 0; virtual void Regist(Texture* tex) = 0;
virtual void PlatromDestroy(Texture* tex) = 0; virtual void PlatromDestroy(Texture* tex) = 0;
virtual void Bind3D(const VolumeTexture3D* tex) = 0;
virtual void UnBind3D(const VolumeTexture3D* tex) = 0;
virtual void Apply3D(VolumeTexture3D* tex) = 0;
virtual void Regist3D(VolumeTexture3D* tex) = 0;
virtual void PlatromDestroy3D(VolumeTexture3D* tex) = 0;
}; };
} // namespace TSE } // namespace TSE

View File

@@ -3,6 +3,9 @@
#include "BehaviourScriptRegistry.hpp" #include "BehaviourScriptRegistry.hpp"
#include "BehaviourScripts/AudioListener.hpp" #include "BehaviourScripts/AudioListener.hpp"
#include "BehaviourScripts/AudioSource.hpp" #include "BehaviourScripts/AudioSource.hpp"
#include "BehaviourScripts/TileMap.hpp"
#include "BehaviourScripts/OrdererSpriteSet.hpp"
#include "BehaviourScripts/PhysicsObject.hpp"
#include "BehaviourScripts/basicEditorCamera.hpp" #include "BehaviourScripts/basicEditorCamera.hpp"
TSE::EDITOR::EditorSubsystem::EditorSubsystem() : sv(nullptr), editorLayer("") TSE::EDITOR::EditorSubsystem::EditorSubsystem() : sv(nullptr), editorLayer("")
@@ -26,6 +29,9 @@ TSE::EDITOR::EditorSubsystem::EditorSubsystem() : sv(nullptr), editorLayer("")
BehaviourScriptRegistry::RegisterBehaviourScript("Camera", []() -> BehaviourScript* {return new Camera();}); BehaviourScriptRegistry::RegisterBehaviourScript("Camera", []() -> BehaviourScript* {return new Camera();});
BehaviourScriptRegistry::RegisterBehaviourScript("Audio Listener", []() -> BehaviourScript* {return new AudioListener();}); BehaviourScriptRegistry::RegisterBehaviourScript("Audio Listener", []() -> BehaviourScript* {return new AudioListener();});
BehaviourScriptRegistry::RegisterBehaviourScript("Audio Source", []() -> BehaviourScript* {return new AudioSource();}); BehaviourScriptRegistry::RegisterBehaviourScript("Audio Source", []() -> BehaviourScript* {return new AudioSource();});
BehaviourScriptRegistry::RegisterBehaviourScript("Tile Map", []() -> BehaviourScript* {return new TileMap();});
BehaviourScriptRegistry::RegisterBehaviourScript("Orderer Sprite Set", []() -> BehaviourScript* {return new OrdererSpriteSet();});
BehaviourScriptRegistry::RegisterBehaviourScript("Physics Object", []() -> BehaviourScript* { return new PhysicsObject(BodyType::Dynamic, ColliderShape::Box, 1.0f, 0.3f, Vector3(1, 1, 0)); });
#pragma region camerastuff #pragma region camerastuff
@@ -43,4 +49,4 @@ TSE::EDITOR::EditorSubsystem::EditorSubsystem() : sv(nullptr), editorLayer("")
editorLayer.SetNonVisual(true); editorLayer.SetNonVisual(true);
#pragma endregion #pragma endregion
} }

View File

@@ -208,6 +208,10 @@ namespace TSE::EDITOR
{ {
Draw((TileMap*)element, debug); Draw((TileMap*)element, debug);
} }
else if (name == "Orderer Sprite Set")
{
Draw((OrdererSpriteSet*)element, debug);
}
else else
{ {
element->CustomDraw(debug); element->CustomDraw(debug);
@@ -915,6 +919,30 @@ namespace TSE::EDITOR
ImGui::TextDisabled(("Chunk Count: " + std::to_string(element->GetChunkCount())).c_str()); ImGui::TextDisabled(("Chunk Count: " + std::to_string(element->GetChunkCount())).c_str());
} }
} }
void ElementDrawer::Draw(OrdererSpriteSet *element, const bool &debug)
{
int orderIndex = static_cast<int>(element->order);
const char* orderItems[] = { "TopRight", "TopLeft", "BottomRight", "BottomLeft" };
if (ImGui::Combo("Order", &orderIndex, orderItems, IM_ARRAYSIZE(orderItems)))
{
element->order = static_cast<SortingOrder>(orderIndex);
for (auto& [_, chunk] : element->chunks)
{
chunk.SetOrdering(element->order);
}
element->DirtyAll();
}
ImGui::BeginDisabled();
ImGui::DragInt("Chunk Size", &element->chunkSize, 1.0f);
ImGui::EndDisabled();
if (debug)
{
ImGui::Separator();
ImGui::TextDisabled(("Chunk Count: " + std::to_string(element->GetChunkCount())).c_str());
}
}
void ElementDrawer::DrawAudioClipCompact(AudioClip *element, const bool &debug, const std::string &label) void ElementDrawer::DrawAudioClipCompact(AudioClip *element, const bool &debug, const std::string &label)
{ {
float item_spacing = ImGui::GetStyle().ItemSpacing.x; float item_spacing = ImGui::GetStyle().ItemSpacing.x;

View File

@@ -14,6 +14,7 @@
#include "BehaviourScripts/AudioListener.hpp" #include "BehaviourScripts/AudioListener.hpp"
#include "BehaviourScripts/AudioSource.hpp" #include "BehaviourScripts/AudioSource.hpp"
#include "BehaviourScripts/TileMap.hpp" #include "BehaviourScripts/TileMap.hpp"
#include "BehaviourScripts/OrdererSpriteSet.hpp"
namespace TSE::EDITOR namespace TSE::EDITOR
{ {
@@ -81,6 +82,7 @@ namespace TSE::EDITOR
static void Draw(Camera* element, const bool& debug); static void Draw(Camera* element, const bool& debug);
static void Draw(ParticleSystem* element, const bool& debug); static void Draw(ParticleSystem* element, const bool& debug);
static void Draw(TileMap* element, const bool& debug); static void Draw(TileMap* element, const bool& debug);
static void Draw(OrdererSpriteSet* element, const bool& debug);
static void DrawAudioClipCompact(AudioClip* element, const bool& debug, const std::string& label); static void DrawAudioClipCompact(AudioClip* element, const bool& debug, const std::string& label);
static void DrawAudioClipNormal(AudioClip* element, const bool& debug, const std::string& label); static void DrawAudioClipNormal(AudioClip* element, const bool& debug, const std::string& label);

View File

@@ -5,7 +5,7 @@
#include "imgui/imgui.h" #include "imgui/imgui.h"
#include "extern/imgui_impl_opengl3.h" #include "extern/imgui_impl_opengl3.h"
#include "PathHelper.hpp" #include "PathHelper.hpp"
#include "elements/Texture.hpp" #include "interfaces/ITexture.hpp"
#include "TextureHelperOpenGL.hpp" #include "TextureHelperOpenGL.hpp"
#include "interfaces/IRenderer.hpp" #include "interfaces/IRenderer.hpp"
#include "BehaviourScripts/Camera.hpp" #include "BehaviourScripts/Camera.hpp"
@@ -55,7 +55,7 @@ TSE::OpenGL::OpenGLRenderingBackend::~OpenGLRenderingBackend()
void TSE::OpenGL::OpenGLRenderingBackend::InitPreWindow() void TSE::OpenGL::OpenGLRenderingBackend::InitPreWindow()
{ {
IRenderTexture::factory = new RenderTextureCreatorOpenGL(); IRenderTexture::factory = new RenderTextureCreatorOpenGL();
Texture::helper = new TextureHelperOpenGL(); ITexture::helper = new TextureHelperOpenGL();
Camera::helper = new CameraHelperOpenGL(); Camera::helper = new CameraHelperOpenGL();
#if defined(TSE_GLFW) #if defined(TSE_GLFW)

View File

@@ -1,61 +1,165 @@
#include "GL/gl3w.h" #include "GL/gl3w.h"
#include "GL/gl.h" #include "GL/gl.h"
#include "TextureHelperOpenGL.hpp" #include "TextureHelperOpenGL.hpp"
void TSE::OpenGL::TextureHelperOpenGL::Bind(const Texture *tex) void TSE::OpenGL::TextureHelperOpenGL::Bind(const Texture *tex)
{ {
glBindTexture(GL_TEXTURE_2D, tex->GetTextureId()); glBindTexture(GL_TEXTURE_2D, tex->GetTextureId());
} }
void TSE::OpenGL::TextureHelperOpenGL::UnBind(const Texture *tex) void TSE::OpenGL::TextureHelperOpenGL::UnBind(const Texture *tex)
{ {
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
} }
void TSE::OpenGL::TextureHelperOpenGL::Apply(Texture *tex) void TSE::OpenGL::TextureHelperOpenGL::Apply(Texture *tex)
{ {
glBindTexture(GL_TEXTURE_2D, tex->GetTextureId()); glBindTexture(GL_TEXTURE_2D, tex->GetTextureId());
if(tex->Chanels() == 1) if(tex->Chanels() == 1)
{ {
if (tex->bpp() == 8) if (tex->bpp() == 8)
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->Width(), tex->Height(), 0, GL_RED, GL_UNSIGNED_BYTE, tex->GetImagePtr()); glTexImage2D(GL_TEXTURE_2D, 0,GL_R8, tex->Width(), tex->Height(), 0, GL_RED, GL_UNSIGNED_BYTE, tex->GetImagePtr());
} if (tex->bpp() == 16)
if(tex->Chanels() == 3) glTexImage2D(GL_TEXTURE_2D, 0, GL_R16I, tex->Width(), tex->Height(), 0, GL_RED, GL_SHORT, tex->GetImagePtr());
{ }
if(tex->bpp() == 24) if(tex->Chanels() == 3)
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->Width(), tex->Height(), 0, GL_BGR, GL_UNSIGNED_BYTE, tex->GetImagePtr()); {
} if(tex->bpp() == 24)
else if(tex->Chanels() == 4) glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, tex->Width(), tex->Height(), 0, GL_BGR, GL_UNSIGNED_BYTE, tex->GetImagePtr());
{ }
if(tex->bpp() == 32) else if(tex->Chanels() == 4)
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->Width(), tex->Height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, tex->GetImagePtr()); {
if (tex->bpp() == 8) //need to decode it with bitwise operations in shader if(tex->bpp() == 32)
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->Width(), tex->Height(), 0, GL_RED, GL_UNSIGNED_BYTE, tex->GetImagePtr()); glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->Width(), tex->Height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, tex->GetImagePtr());
} if (tex->bpp() == 8) //need to decode it with bitwise operations in shader
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA2, tex->Width(), tex->Height(), 0, GL_RED, GL_UNSIGNED_BYTE, tex->GetImagePtr());
glGenerateMipmap(GL_TEXTURE_2D); }
glBindTexture(GL_TEXTURE_2D, 0); glGenerateMipmap(GL_TEXTURE_2D);
}
glBindTexture(GL_TEXTURE_2D, 0);
void TSE::OpenGL::TextureHelperOpenGL::Regist(Texture *tex) }
{
uint TextureID; void TSE::OpenGL::TextureHelperOpenGL::Regist(Texture *tex)
{
glGenTextures(1, &TextureID); uint TextureID;
glBindTexture(GL_TEXTURE_2D, TextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glGenTextures(1, &TextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, TextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
tex->SetTextureId(TextureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
tex->Apply(); tex->SetTextureId(TextureID);
}
tex->Apply();
void TSE::OpenGL::TextureHelperOpenGL::PlatromDestroy(Texture *tex) }
{
uint id = tex->GetTextureId(); void TSE::OpenGL::TextureHelperOpenGL::PlatromDestroy(Texture *tex)
glDeleteTextures(1, &id); {
} uint id = tex->GetTextureId();
glDeleteTextures(1, &id);
}
void TSE::OpenGL::TextureHelperOpenGL::Bind3D(const VolumeTexture3D *tex)
{
glBindTexture(GL_TEXTURE_3D, tex->GetTextureId());
}
void TSE::OpenGL::TextureHelperOpenGL::UnBind3D(const VolumeTexture3D *tex)
{
glBindTexture(GL_TEXTURE_3D, 0);
}
void TSE::OpenGL::TextureHelperOpenGL::Apply3D(VolumeTexture3D *tex)
{
glBindTexture(GL_TEXTURE_3D, tex->GetTextureId());
ushort internal,input,size;
if(tex->Chanels() == 1)
{
if (tex->bpp() == 8)
{
internal = GL_R8;
input = GL_RED;
size = GL_UNSIGNED_BYTE;
}
if (tex->bpp() == 16)
{
internal = GL_R16I;
input = GL_RED;
size = GL_SHORT;
}
}
if(tex->Chanels() == 3)
{
if(tex->bpp() == 24)
{
internal = GL_RGB;
input = GL_BGR;
size = GL_UNSIGNED_BYTE;
}
}
else if(tex->Chanels() == 4)
{
if(tex->bpp() == 32)
{
internal = GL_R16;
input = GL_BGRA;
size = GL_UNSIGNED_BYTE;
}
if (tex->bpp() == 8) //need to decode it with bitwise operations in shader
{
internal = GL_RGBA2;
input = GL_RED;
size = GL_UNSIGNED_BYTE;
}
}
glTexImage3D(GL_TEXTURE_3D, 0, internal, tex->Width(), tex->Height(), tex->Depth(), 0, input, size, nullptr);
for (int z = 0; z < tex->Depth(); ++z)
{
glTexSubImage3D(
GL_TEXTURE_3D,
0,
0,
0,
z,
tex->Width(),
tex->Height(),
1,
input,
size,
tex->GetImagePtr(z)
);
}
//glGenerateMipmap(GL_TEXTURE_3D);
glBindTexture(GL_TEXTURE_3D, 0);
}
void TSE::OpenGL::TextureHelperOpenGL::Regist3D(VolumeTexture3D *tex)
{
uint TextureID;
glGenTextures(1, &TextureID);
glBindTexture(GL_TEXTURE_3D, TextureID);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
tex->SetTextureId(TextureID);
tex->Apply();
}
void TSE::OpenGL::TextureHelperOpenGL::PlatromDestroy3D(VolumeTexture3D *tex)
{
uint id = tex->GetTextureId();
glDeleteTextures(1, &id);
}

View File

@@ -2,6 +2,7 @@
#include "interfaces/ITextureHelper.hpp" #include "interfaces/ITextureHelper.hpp"
#include "elements/Texture.hpp" #include "elements/Texture.hpp"
#include "elements/VolumeTexture3D.hpp"
namespace TSE::OpenGL namespace TSE::OpenGL
{ {
@@ -13,5 +14,11 @@ namespace TSE::OpenGL
void Apply(Texture* tex) override; void Apply(Texture* tex) override;
void Regist(Texture* tex) override; void Regist(Texture* tex) override;
void PlatromDestroy(Texture* tex) override; void PlatromDestroy(Texture* tex) override;
void Bind3D(const VolumeTexture3D* tex) override;
void UnBind3D(const VolumeTexture3D* tex) override;
void Apply3D(VolumeTexture3D* tex) override;
void Regist3D(VolumeTexture3D* tex) override;
void PlatromDestroy3D(VolumeTexture3D* tex) override;
}; };
} // namespace TSE::OpenGL } // namespace TSE::OpenGL