mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Feat] (MG_State/Texture): Initial implementation of cube map
This commit is contained in:
@@ -142,6 +142,7 @@ set(SOURCE_FILES
|
|||||||
MobileGL/MG_State/GLState/TextureState/TextureObject.cpp
|
MobileGL/MG_State/GLState/TextureState/TextureObject.cpp
|
||||||
MobileGL/MG_State/GLState/TextureState/TextureObject1D.cpp
|
MobileGL/MG_State/GLState/TextureState/TextureObject1D.cpp
|
||||||
MobileGL/MG_State/GLState/TextureState/TextureObject2D.cpp
|
MobileGL/MG_State/GLState/TextureState/TextureObject2D.cpp
|
||||||
|
MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp
|
||||||
MobileGL/MG_State/GLState/TextureState/TextureObject3D.cpp
|
MobileGL/MG_State/GLState/TextureState/TextureObject3D.cpp
|
||||||
MobileGL/MG_State/GLState/TextureState/TextureUnit.cpp
|
MobileGL/MG_State/GLState/TextureState/TextureUnit.cpp
|
||||||
MobileGL/MG_State/GLState/TextureState/TextureState.cpp
|
MobileGL/MG_State/GLState/TextureState/TextureState.cpp
|
||||||
|
|||||||
@@ -296,13 +296,22 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
GLenum glInternalFormat, glType, glFormat;
|
GLenum glInternalFormat, glType, glFormat;
|
||||||
TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType,
|
TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType,
|
||||||
&glFormat);
|
&glFormat);
|
||||||
|
|
||||||
|
const auto& uploadTargets = stateTextureObject->GetUploadTargets();
|
||||||
|
for (auto uploadTarget: uploadTargets) {
|
||||||
for (SizeT level = 0; level < mipmapCount; ++level) {
|
for (SizeT level = 0; level < mipmapCount; ++level) {
|
||||||
// TODO: deal with multiple upload target texture
|
auto levelTexelSize = stateTextureObject->GetMipmapTexelSize(
|
||||||
auto levelTexelSize = stateTextureObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, level);
|
uploadTarget, level);
|
||||||
auto levelByteSize = stateTextureObject->GetMipmapByteSize(TextureUploadTarget::Texture2D, level);
|
auto levelByteSize = stateTextureObject->GetMipmapByteSize(
|
||||||
bool levelDirty = stateTextureObject->IsStorageDirty(TextureUploadTarget::Texture2D, 0);
|
uploadTarget, level);
|
||||||
auto* pData = (levelDirty && levelByteSize != 0) ? stateTextureObject->MapMipmapData(TextureUploadTarget::Texture2D, level) : nullptr;
|
bool levelDirty = stateTextureObject->IsStorageDirty(
|
||||||
MGLOG_D("%s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p", __func__,
|
uploadTarget, 0);
|
||||||
|
auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget);
|
||||||
|
auto *pData = (levelDirty && levelByteSize != 0)
|
||||||
|
? stateTextureObject->MapMipmapData(
|
||||||
|
uploadTarget, level) : nullptr;
|
||||||
|
MGLOG_D("%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p", __func__,
|
||||||
|
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(),
|
||||||
level,
|
level,
|
||||||
levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(),
|
levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(),
|
||||||
levelByteSize,
|
levelByteSize,
|
||||||
@@ -311,15 +320,20 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER);
|
BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER);
|
||||||
errorLopper.Clear();
|
errorLopper.Clear();
|
||||||
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
MG_External::GLES::glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), glInternalFormat,
|
MG_External::GLES::glTexImage2D(glUploadTarget, static_cast<GLint>(level),
|
||||||
|
glInternalFormat,
|
||||||
static_cast<GLsizei>(levelTexelSize.x()),
|
static_cast<GLsizei>(levelTexelSize.x()),
|
||||||
static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat, glType,
|
static_cast<GLsizei>(levelTexelSize.y()), 0,
|
||||||
|
glFormat, glType,
|
||||||
pData);
|
pData);
|
||||||
|
|
||||||
// TODO: handle more texture types
|
// TODO: handle more texture types
|
||||||
|
|
||||||
MGLOG_D("Regenerated mipmap level %d for texture with ID: %u", level, m_backendTextureId);
|
MGLOG_D("Regenerated mipmap level %d for texture with ID: %u", level,
|
||||||
stateTextureObject->MarkStorageDirty(TextureUploadTarget::Texture2D, level, false);
|
m_backendTextureId);
|
||||||
|
stateTextureObject->MarkStorageDirty(uploadTarget, level,
|
||||||
|
false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
@@ -429,30 +443,41 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
GLenum glInternalFormat, glType, glFormat;
|
GLenum glInternalFormat, glType, glFormat;
|
||||||
TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType,
|
TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType,
|
||||||
&glFormat);
|
&glFormat);
|
||||||
|
const auto& uploadTargets = stateTextureObject->GetUploadTargets();
|
||||||
|
for (auto uploadTarget: uploadTargets) {
|
||||||
for (SizeT level = 0; level < mipmapCount; ++level) {
|
for (SizeT level = 0; level < mipmapCount; ++level) {
|
||||||
if (!stateTextureObject->IsStorageDirty(TextureUploadTarget::Texture2D, level)) {
|
if (!stateTextureObject->IsStorageDirty(uploadTarget, level)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto byteSize = stateTextureObject->GetMipmapByteSize(TextureUploadTarget::Texture2D, level);
|
auto byteSize = stateTextureObject->GetMipmapByteSize(
|
||||||
|
uploadTarget, level);
|
||||||
if (byteSize == 0) {
|
if (byteSize == 0) {
|
||||||
MGLOG_W("Mipmap level %d has no data, skipping update.", level);
|
MGLOG_W("Mipmap level %d has no data, skipping update.", level);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget);
|
||||||
|
|
||||||
BufferImpl::BackendBufferBindingProtector pixelUnpackProtector =
|
BufferImpl::BackendBufferBindingProtector pixelUnpackProtector =
|
||||||
BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER);
|
BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER);
|
||||||
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
|
errorLopper.Loop(
|
||||||
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
|
[file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
|
||||||
|
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line,
|
||||||
|
MG_Util::ConvertGLEnumToString(err).c_str());
|
||||||
});
|
});
|
||||||
auto texelSize = stateTextureObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, level);
|
auto texelSize = stateTextureObject->GetMipmapTexelSize(
|
||||||
MG_External::GLES::glTexSubImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), 0, 0,
|
uploadTarget, level);
|
||||||
|
MG_External::GLES::glTexSubImage2D(glUploadTarget, static_cast<GLint>(level),
|
||||||
|
0, 0,
|
||||||
static_cast<GLsizei>(texelSize.x()),
|
static_cast<GLsizei>(texelSize.x()),
|
||||||
static_cast<GLsizei>(texelSize.y()), glFormat, glType,
|
static_cast<GLsizei>(texelSize.y()),
|
||||||
(byteSize != 0) ? stateTextureObject->MapMipmapData(TextureUploadTarget::Texture2D, level) : nullptr);
|
glFormat, glType,
|
||||||
|
stateTextureObject->MapMipmapData(uploadTarget, level));
|
||||||
|
|
||||||
stateTextureObject->MarkStorageDirty(TextureUploadTarget::Texture2D, level, false);
|
stateTextureObject->MarkStorageDirty(uploadTarget, level, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
|
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
|
||||||
|
|||||||
@@ -114,12 +114,10 @@ namespace MobileGL {
|
|||||||
|
|
||||||
void TextureObjectWithOneMipmap::AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
void TextureObjectWithOneMipmap::AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
||||||
MipmapInput input) {
|
MipmapInput input) {
|
||||||
// don't care target, index always 0
|
|
||||||
m_textureStorage.AllocateLevel(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input);
|
m_textureStorage.AllocateLevel(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input);
|
||||||
}
|
}
|
||||||
void TextureObjectWithOneMipmap::UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
void TextureObjectWithOneMipmap::UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
||||||
DataPtr input) {
|
DataPtr input) {
|
||||||
// ditto
|
|
||||||
m_textureStorage.UpdateSubData(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input);
|
m_textureStorage.UpdateSubData(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input);
|
||||||
}
|
}
|
||||||
void* TextureObjectWithOneMipmap::MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) {
|
void* TextureObjectWithOneMipmap::MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) {
|
||||||
@@ -127,7 +125,6 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextureObjectWithOneMipmap::MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) {
|
void TextureObjectWithOneMipmap::MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) {
|
||||||
// ditto
|
|
||||||
m_textureStorage.MarkDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, dirty);
|
m_textureStorage.MarkDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ namespace MobileGL {
|
|||||||
|
|
||||||
virtual TextureInternalFormat GetFormat() const = 0;
|
virtual TextureInternalFormat GetFormat() const = 0;
|
||||||
virtual TextureTarget GetTarget() const = 0;
|
virtual TextureTarget GetTarget() const = 0;
|
||||||
|
virtual const Vector<TextureUploadTarget>& GetUploadTargets() const = 0;
|
||||||
virtual IntVec3 GetBaseSize() const = 0;
|
virtual IntVec3 GetBaseSize() const = 0;
|
||||||
virtual SharedPtr<SamplerObject> GetSamplerObject() const = 0;
|
virtual SharedPtr<SamplerObject> GetSamplerObject() const = 0;
|
||||||
virtual void SetInternalFormat(TextureInternalFormat format) = 0;
|
virtual void SetInternalFormat(TextureInternalFormat format) = 0;
|
||||||
|
|||||||
@@ -7,9 +7,12 @@ namespace MobileGL {
|
|||||||
class TextureObject1D : public TextureObjectWithOneMipmap {
|
class TextureObject1D : public TextureObjectWithOneMipmap {
|
||||||
public:
|
public:
|
||||||
explicit TextureObject1D(Uint externalIndex);
|
explicit TextureObject1D(Uint externalIndex);
|
||||||
|
const Vector<TextureUploadTarget>& GetUploadTargets() const override {
|
||||||
|
return m_uploadTargets;
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
|
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
|
||||||
|
const Vector<TextureUploadTarget> m_uploadTargets {TextureUploadTarget::Texture1D};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,12 @@ namespace MobileGL {
|
|||||||
class TextureObject2D : public TextureObjectWithOneMipmap {
|
class TextureObject2D : public TextureObjectWithOneMipmap {
|
||||||
public:
|
public:
|
||||||
explicit TextureObject2D(Uint externalIndex);
|
explicit TextureObject2D(Uint externalIndex);
|
||||||
|
const Vector<TextureUploadTarget>& GetUploadTargets() const override {
|
||||||
|
return m_uploadTargets;
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
|
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
|
||||||
|
const Vector<TextureUploadTarget> m_uploadTargets {TextureUploadTarget::Texture2D};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#include "TextureObject2DCube.h"
|
||||||
|
|
||||||
|
namespace MobileGL {
|
||||||
|
namespace MG_State {
|
||||||
|
namespace GLState {
|
||||||
|
TextureObject2DCube::TextureObject2DCube(Uint externalIndex):
|
||||||
|
TextureObjectBase(TextureTarget::TextureCubeMap, externalIndex) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint TextureObject2DCube::GetMipmapLevelCount() const {
|
||||||
|
return m_textureStorage.GetLevelCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
const IntVec3 TextureObject2DCube::GetMipmapTexelSize(TextureUploadTarget target,
|
||||||
|
Uint mipmapLevel) const {
|
||||||
|
return m_textureStorage.GetTexelSize(GetIndexOfTextureUploadTarget(target), mipmapLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
const SizeT TextureObject2DCube::GetMipmapByteSize(TextureUploadTarget target,
|
||||||
|
Uint mipmapLevel) const {
|
||||||
|
return m_textureStorage.GetByteSize(GetIndexOfTextureUploadTarget(target), mipmapLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextureObject2DCube::AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
||||||
|
MipmapInput input) {
|
||||||
|
m_textureStorage.AllocateLevel(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureObject2DCube::UpdateMipmapSubData(TextureUploadTarget uploadTarget,
|
||||||
|
Uint mipmapLevel, DataPtr input) {
|
||||||
|
m_textureStorage.UpdateSubData(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
TextureObject2DCube::MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) {
|
||||||
|
return m_textureStorage.MapData(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureObject2DCube::MarkStorageDirty(TextureUploadTarget uploadTarget,
|
||||||
|
Uint mipmapLevel, bool dirty) {
|
||||||
|
m_textureStorage.MarkDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, dirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TextureObject2DCube::IsStorageDirty(TextureUploadTarget uploadTarget,
|
||||||
|
Uint mipmapLevel) const {
|
||||||
|
return m_textureStorage.IsDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint
|
||||||
|
TextureObject2DCube::GetIndexOfTextureUploadTarget(TextureUploadTarget target) const {
|
||||||
|
MOBILEGL_ASSERT(TextureUploadTarget::CubeMapPositiveX <= target && target <= TextureUploadTarget::ProxyCubeMap,
|
||||||
|
"Invalid TextureUploadTarget!");
|
||||||
|
return (Uint)target - (Uint)TextureUploadTarget::CubeMapPositiveX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "TextureObject.h"
|
||||||
|
|
||||||
|
namespace MobileGL {
|
||||||
|
namespace MG_State {
|
||||||
|
namespace GLState {
|
||||||
|
class TextureObject2DCube : public TextureObjectBase {
|
||||||
|
public:
|
||||||
|
explicit TextureObject2DCube(Uint externalIndex);
|
||||||
|
|
||||||
|
const Vector<TextureUploadTarget>& GetUploadTargets() const override {
|
||||||
|
return m_uploadTargets;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint GetMipmapLevelCount() const override;
|
||||||
|
const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const override;
|
||||||
|
const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const override;
|
||||||
|
void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) override;
|
||||||
|
void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) override;
|
||||||
|
void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) override;
|
||||||
|
void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) override;
|
||||||
|
bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const override;
|
||||||
|
protected:
|
||||||
|
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
|
||||||
|
TextureStorage<6> m_textureStorage;
|
||||||
|
const Vector<TextureUploadTarget> m_uploadTargets {
|
||||||
|
TextureUploadTarget::CubeMapPositiveX,
|
||||||
|
TextureUploadTarget::CubeMapNegativeX,
|
||||||
|
TextureUploadTarget::CubeMapPositiveY,
|
||||||
|
TextureUploadTarget::CubeMapNegativeY,
|
||||||
|
TextureUploadTarget::CubeMapPositiveZ,
|
||||||
|
TextureUploadTarget::CubeMapNegativeZ,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,9 +7,12 @@ namespace MobileGL {
|
|||||||
class TextureObject3D : public TextureObjectWithOneMipmap {
|
class TextureObject3D : public TextureObjectWithOneMipmap {
|
||||||
public:
|
public:
|
||||||
explicit TextureObject3D(Uint externalIndex);
|
explicit TextureObject3D(Uint externalIndex);
|
||||||
|
const Vector<TextureUploadTarget>& GetUploadTargets() const override {
|
||||||
|
return m_uploadTargets;
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
|
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
|
||||||
|
const Vector<TextureUploadTarget> m_uploadTargets {TextureUploadTarget::Texture3D};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "MG_State/GLState/TextureState/TextureObject2D.h"
|
#include "MG_State/GLState/TextureState/TextureObject2D.h"
|
||||||
#include "MG_State/GLState/TextureState/TextureObject3D.h"
|
#include "MG_State/GLState/TextureState/TextureObject3D.h"
|
||||||
#include "MG_Util/Types.h"
|
#include "MG_Util/Types.h"
|
||||||
|
#include "TextureObject2DCube.h"
|
||||||
|
|
||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
namespace MG_State {
|
namespace MG_State {
|
||||||
@@ -34,7 +35,9 @@ namespace MobileGL {
|
|||||||
case TextureTarget::Texture1D:
|
case TextureTarget::Texture1D:
|
||||||
textureObject = MakeShared<TextureObject1D>(index);
|
textureObject = MakeShared<TextureObject1D>(index);
|
||||||
break;
|
break;
|
||||||
case TextureTarget::TextureCubeMap: // TODO
|
case TextureTarget::TextureCubeMap:
|
||||||
|
textureObject = MakeShared<TextureObject2DCube>(index);
|
||||||
|
break;
|
||||||
case TextureTarget::Texture2D:
|
case TextureTarget::Texture2D:
|
||||||
textureObject = MakeShared<TextureObject2D>(index);
|
textureObject = MakeShared<TextureObject2D>(index);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user