mirror of
https://github.com/overte-org/overte.git
synced 2025-07-23 13:44:32 +02:00
refactoring th ecube texure loading to support 2 different layouts
This commit is contained in:
parent
9c27106435
commit
f1fcce3ea0
5 changed files with 235 additions and 141 deletions
|
@ -295,8 +295,8 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
||||||
glBindTexture(GL_TEXTURE_2D, object->_texture);
|
glBindTexture(GL_TEXTURE_2D, object->_texture);
|
||||||
|
|
||||||
if (needUpdate) {
|
if (needUpdate) {
|
||||||
if (texture.isStoredMipAvailable(0)) {
|
if (texture.isStoredMipFaceAvailable(0)) {
|
||||||
Texture::PixelsPointer mip = texture.accessStoredMip(0);
|
Texture::PixelsPointer mip = texture.accessStoredMipFace(0);
|
||||||
const GLvoid* bytes = mip->_sysmem.read<Byte>();
|
const GLvoid* bytes = mip->_sysmem.read<Byte>();
|
||||||
Element srcFormat = mip->_format;
|
Element srcFormat = mip->_format;
|
||||||
|
|
||||||
|
@ -318,15 +318,15 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
||||||
|
|
||||||
|
|
||||||
// At this point the mip piels have been loaded, we can notify
|
// At this point the mip piels have been loaded, we can notify
|
||||||
texture.notifyGPULoaded(0);
|
texture.notifyMipFaceGPULoaded(0, 0);
|
||||||
|
|
||||||
object->_contentStamp = texture.getDataStamp();
|
object->_contentStamp = texture.getDataStamp();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const GLvoid* bytes = 0;
|
const GLvoid* bytes = 0;
|
||||||
Element srcFormat = texture.getTexelFormat();
|
Element srcFormat = texture.getTexelFormat();
|
||||||
if (texture.isStoredMipAvailable(0)) {
|
if (texture.isStoredMipFaceAvailable(0)) {
|
||||||
Texture::PixelsPointer mip = texture.accessStoredMip(0);
|
Texture::PixelsPointer mip = texture.accessStoredMipFace(0);
|
||||||
|
|
||||||
bytes = mip->_sysmem.read<Byte>();
|
bytes = mip->_sysmem.read<Byte>();
|
||||||
srcFormat = mip->_format;
|
srcFormat = mip->_format;
|
||||||
|
@ -352,10 +352,11 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
||||||
|
|
||||||
syncSampler(texture.getSampler(), texture.getType(), object);
|
syncSampler(texture.getSampler(), texture.getType(), object);
|
||||||
|
|
||||||
// At this point the mip piels have been loaded, we can notify
|
// At this point the mip pixels have been loaded, we can notify
|
||||||
texture.notifyGPULoaded(0);
|
texture.notifyMipFaceGPULoaded(0, 0);
|
||||||
|
|
||||||
object->_storageStamp = texture.getStamp();
|
object->_storageStamp = texture.getStamp();
|
||||||
|
object->_contentStamp = texture.getDataStamp();
|
||||||
object->_size = texture.getSize();
|
object->_size = texture.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,75 +371,57 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture);
|
glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture);
|
||||||
const int NUM_FACES = 6;
|
const int NUM_FACES = 6;
|
||||||
const GLenum FACE_LAYOUT[] = {
|
const GLenum FACE_LAYOUT[] = {
|
||||||
/* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
|
|
||||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
|
|
||||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_X };
|
|
||||||
*/
|
|
||||||
GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
|
||||||
|
|
||||||
/* GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
|
||||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
|
|
||||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
|
|
||||||
*/
|
|
||||||
/* GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
|
||||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
|
||||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };*/
|
|
||||||
if (needUpdate) {
|
if (needUpdate) {
|
||||||
if (texture.isStoredMipAvailable(0)) {
|
|
||||||
Texture::PixelsPointer mip = texture.accessStoredMip(0);
|
|
||||||
Element srcFormat = mip->_format;
|
|
||||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
|
|
||||||
|
|
||||||
uint16 width = texture.getWidth();
|
|
||||||
int faceSize = mip->_sysmem.getSize() / NUM_FACES;
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture);
|
|
||||||
for (int f = 0; f < NUM_FACES; f++) {
|
|
||||||
glTexSubImage2D(FACE_LAYOUT[f], 0, texelFormat.internalFormat, width, width, 0,
|
|
||||||
texelFormat.format, texelFormat.type, (GLvoid*) (mip->_sysmem.read<Byte>() + f * faceSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture.isAutogenerateMips()) {
|
|
||||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
object->_target = GL_TEXTURE_CUBE_MAP;
|
|
||||||
|
|
||||||
syncSampler(texture.getSampler(), texture.getType(), object);
|
|
||||||
|
|
||||||
// At this point the mip piels have been loaded, we can notify
|
|
||||||
texture.notifyGPULoaded(0);
|
|
||||||
|
|
||||||
object->_contentStamp = texture.getDataStamp();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const gpu::Byte* bytes = 0;
|
|
||||||
Element srcFormat = texture.getTexelFormat();
|
|
||||||
uint16 width = texture.getWidth();
|
|
||||||
int faceSize = 0;
|
|
||||||
|
|
||||||
if (texture.isStoredMipAvailable(0)) {
|
|
||||||
Texture::PixelsPointer mip = texture.accessStoredMip(0);
|
|
||||||
|
|
||||||
bytes = mip->_sysmem.read<Byte>();
|
|
||||||
srcFormat = mip->_format;
|
|
||||||
faceSize = mip->_sysmem.getSize() / NUM_FACES;
|
|
||||||
|
|
||||||
object->_contentStamp = texture.getDataStamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture);
|
glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture);
|
||||||
|
|
||||||
|
// transfer pixels from each faces
|
||||||
for (int f = 0; f < NUM_FACES; f++) {
|
for (int f = 0; f < NUM_FACES; f++) {
|
||||||
glTexImage2D(FACE_LAYOUT[f], 0, texelFormat.internalFormat, width, width, 0,
|
if (texture.isStoredMipFaceAvailable(0, f)) {
|
||||||
texelFormat.format, texelFormat.type, (GLvoid*) (bytes + f * faceSize));
|
Texture::PixelsPointer mipFace = texture.accessStoredMipFace(0, f);
|
||||||
|
Element srcFormat = mipFace->_format;
|
||||||
|
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
|
||||||
|
|
||||||
|
glTexSubImage2D(FACE_LAYOUT[f], 0, texelFormat.internalFormat, texture.getWidth(), texture.getWidth(), 0,
|
||||||
|
texelFormat.format, texelFormat.type, (GLvoid*) (mipFace->_sysmem.read<Byte>()));
|
||||||
|
|
||||||
|
// At this point the mip pixels have been loaded, we can notify
|
||||||
|
texture.notifyMipFaceGPULoaded(0, f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes && texture.isAutogenerateMips()) {
|
if (texture.isAutogenerateMips()) {
|
||||||
|
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
object->_target = GL_TEXTURE_CUBE_MAP;
|
||||||
|
|
||||||
|
syncSampler(texture.getSampler(), texture.getType(), object);
|
||||||
|
|
||||||
|
object->_contentStamp = texture.getDataStamp();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture);
|
||||||
|
|
||||||
|
// transfer pixels from each faces
|
||||||
|
for (int f = 0; f < NUM_FACES; f++) {
|
||||||
|
if (texture.isStoredMipFaceAvailable(0, f)) {
|
||||||
|
Texture::PixelsPointer mipFace = texture.accessStoredMipFace(0, f);
|
||||||
|
Element srcFormat = mipFace->_format;
|
||||||
|
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
|
||||||
|
|
||||||
|
glTexImage2D(FACE_LAYOUT[f], 0, texelFormat.internalFormat, texture.getWidth(), texture.getWidth(), 0,
|
||||||
|
texelFormat.format, texelFormat.type, (GLvoid*) (mipFace->_sysmem.read<Byte>()));
|
||||||
|
|
||||||
|
// At this point the mip pixels have been loaded, we can notify
|
||||||
|
texture.notifyMipFaceGPULoaded(0, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture.isAutogenerateMips()) {
|
||||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
} else {
|
} else {
|
||||||
|
@ -450,10 +433,8 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
||||||
|
|
||||||
syncSampler(texture.getSampler(), texture.getType(), object);
|
syncSampler(texture.getSampler(), texture.getType(), object);
|
||||||
|
|
||||||
// At this point the mip piels have been loaded, we can notify
|
|
||||||
texture.notifyGPULoaded(0);
|
|
||||||
|
|
||||||
object->_storageStamp = texture.getStamp();
|
object->_storageStamp = texture.getStamp();
|
||||||
|
object->_contentStamp = texture.getDataStamp();
|
||||||
object->_size = texture.getSize();
|
object->_size = texture.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,69 +28,103 @@ Texture::Pixels::~Pixels() {
|
||||||
|
|
||||||
void Texture::Storage::assignTexture(Texture* texture) {
|
void Texture::Storage::assignTexture(Texture* texture) {
|
||||||
_texture = texture;
|
_texture = texture;
|
||||||
}
|
if (_texture) {
|
||||||
|
_type = _texture->getType();
|
||||||
Stamp Texture::Storage::getStamp(uint16 level) const {
|
|
||||||
PixelsPointer mip = getMip(level);
|
|
||||||
if (mip) {
|
|
||||||
return mip->_sysmem.getStamp();
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::Storage::reset() {
|
void Texture::Storage::reset() {
|
||||||
_mips.clear();
|
_mips.clear();
|
||||||
|
bumpStamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::PixelsPointer Texture::Storage::editMip(uint16 level) {
|
Texture::PixelsPointer Texture::Storage::editMipFace(uint16 level, uint8 face) {
|
||||||
if (level < _mips.size()) {
|
if (level < _mips.size()) {
|
||||||
return _mips[level];
|
assert(face < _mips[level].size());
|
||||||
|
bumpStamp();
|
||||||
|
return _mips[level][face];
|
||||||
}
|
}
|
||||||
return PixelsPointer();
|
return PixelsPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Texture::PixelsPointer Texture::Storage::getMip(uint16 level) const {
|
const Texture::PixelsPointer Texture::Storage::getMipFace(uint16 level, uint8 face) const {
|
||||||
if (level < _mips.size()) {
|
if (level < _mips.size()) {
|
||||||
return _mips[level];
|
assert(face < _mips[level].size());
|
||||||
|
return _mips[level][face];
|
||||||
}
|
}
|
||||||
return PixelsPointer();
|
return PixelsPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::Storage::notifyGPULoaded(uint16 level) const {
|
void Texture::Storage::notifyMipFaceGPULoaded(uint16 level, uint8 face) const {
|
||||||
PixelsPointer mip = getMip(level);
|
PixelsPointer mipFace = getMipFace(level, face);
|
||||||
if (mip) {
|
if (mipFace) {
|
||||||
mip->_isGPULoaded = true;
|
mipFace->_isGPULoaded = true;
|
||||||
mip->_sysmem.resize(0);
|
mipFace->_sysmem.resize(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Texture::Storage::isMipAvailable(uint16 level) const {
|
bool Texture::Storage::isMipAvailable(uint16 level, uint8 face) const {
|
||||||
PixelsPointer mip = getMip(level);
|
PixelsPointer mipFace = getMipFace(level, face);
|
||||||
return (mip && mip->_sysmem.getSize());
|
return (mipFace && mipFace->_sysmem.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Texture::Storage::allocateMip(uint16 level) {
|
bool Texture::Storage::allocateMip(uint16 level) {
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
if (level >= _mips.size()) {
|
if (level >= _mips.size()) {
|
||||||
_mips.resize(level+1, PixelsPointer());
|
_mips.resize(level+1, std::vector<PixelsPointer>(Texture::NUM_FACES_PER_TYPE[getType()]));
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_mips[level]) {
|
auto& mip = _mips[level];
|
||||||
_mips[level] = PixelsPointer(new Pixels());
|
for (auto& face : mip) {
|
||||||
changed = true;
|
if (!face) {
|
||||||
|
face.reset(new Pixels());
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bumpStamp();
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes) {
|
bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes) {
|
||||||
// Ok we should be able to do that...
|
|
||||||
|
allocateMip(level);
|
||||||
|
auto& mip = _mips[level];
|
||||||
|
|
||||||
|
// here we grabbed an array of faces
|
||||||
|
// The bytes assigned here are supposed to contain all the faces bytes of the mip.
|
||||||
|
// For tex1D, 2D, 3D there is only one face
|
||||||
|
// For Cube, we expect the 6 faces in the order X+, X-, Y+, Y-, Z+, Z-
|
||||||
|
int sizePerFace = size / mip.size();
|
||||||
|
auto faceBytes = bytes;
|
||||||
|
Size allocated = 0;
|
||||||
|
for (auto& face : mip) {
|
||||||
|
face->_format = format;
|
||||||
|
allocated += face->_sysmem.setData(sizePerFace, faceBytes);
|
||||||
|
face->_isGPULoaded = false;
|
||||||
|
faceBytes += sizePerFace;
|
||||||
|
}
|
||||||
|
|
||||||
|
bumpStamp();
|
||||||
|
|
||||||
|
return allocated == size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Texture::Storage::assignMipFaceData(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face) {
|
||||||
|
|
||||||
allocateMip(level);
|
allocateMip(level);
|
||||||
auto mip = _mips[level];
|
auto mip = _mips[level];
|
||||||
mip->_format = format;
|
Size allocated = 0;
|
||||||
Size allocated = mip->_sysmem.setData(size, bytes);
|
if (face < mip.size()) {
|
||||||
mip->_isGPULoaded = false;
|
auto mipFace = mip[face];
|
||||||
|
mipFace->_format = format;
|
||||||
|
allocated += mipFace->_sysmem.setData(size, bytes);
|
||||||
|
mipFace->_isGPULoaded = false;
|
||||||
|
bumpStamp();
|
||||||
|
}
|
||||||
|
|
||||||
return allocated == size;
|
return allocated == size;
|
||||||
}
|
}
|
||||||
|
@ -115,8 +149,8 @@ Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, ui
|
||||||
{
|
{
|
||||||
Texture* tex = new Texture();
|
Texture* tex = new Texture();
|
||||||
tex->_storage.reset(new Storage());
|
tex->_storage.reset(new Storage());
|
||||||
tex->_storage->_texture = tex;
|
|
||||||
tex->_type = type;
|
tex->_type = type;
|
||||||
|
tex->_storage->assignTexture(tex);
|
||||||
tex->_maxMip = 0;
|
tex->_maxMip = 0;
|
||||||
tex->resize(type, texelFormat, width, height, depth, numSamples, numSlices);
|
tex->resize(type, texelFormat, width, height, depth, numSamples, numSlices);
|
||||||
|
|
||||||
|
@ -275,6 +309,37 @@ bool Texture::assignStoredMip(uint16 level, const Element& format, Size size, co
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Texture::assignStoredMipFace(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face) {
|
||||||
|
// Check that level accessed make sense
|
||||||
|
if (level != 0) {
|
||||||
|
if (_autoGenerateMips) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (level >= evalNumMips()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// THen check that the mem buffer passed make sense with its format
|
||||||
|
Size expectedSize = evalStoredMipFaceSize(level, format);
|
||||||
|
if (size == expectedSize) {
|
||||||
|
_storage->assignMipFaceData(level, format, size, bytes, face);
|
||||||
|
_stamp++;
|
||||||
|
return true;
|
||||||
|
} else if (size > expectedSize) {
|
||||||
|
// NOTE: We are facing this case sometime because apparently QImage (from where we get the bits) is generating images
|
||||||
|
// and alligning the line of pixels to 32 bits.
|
||||||
|
// We should probably consider something a bit more smart to get the correct result but for now (UI elements)
|
||||||
|
// it seems to work...
|
||||||
|
_storage->assignMipFaceData(level, format, size, bytes, face);
|
||||||
|
_stamp++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
uint16 Texture::autoGenerateMips(uint16 maxMip) {
|
uint16 Texture::autoGenerateMips(uint16 maxMip) {
|
||||||
_autoGenerateMips = true;
|
_autoGenerateMips = true;
|
||||||
_maxMip = std::min((uint16) (evalNumMips() - 1), maxMip);
|
_maxMip = std::min((uint16) (evalNumMips() - 1), maxMip);
|
||||||
|
@ -283,15 +348,15 @@ uint16 Texture::autoGenerateMips(uint16 maxMip) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Texture::getStoredMipWidth(uint16 level) const {
|
uint16 Texture::getStoredMipWidth(uint16 level) const {
|
||||||
PixelsPointer mip = accessStoredMip(level);
|
PixelsPointer mipFace = accessStoredMipFace(level);
|
||||||
if (mip && mip->_sysmem.getSize()) {
|
if (mipFace && mipFace->_sysmem.getSize()) {
|
||||||
return evalMipWidth(level);
|
return evalMipWidth(level);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Texture::getStoredMipHeight(uint16 level) const {
|
uint16 Texture::getStoredMipHeight(uint16 level) const {
|
||||||
PixelsPointer mip = accessStoredMip(level);
|
PixelsPointer mip = accessStoredMipFace(level);
|
||||||
if (mip && mip->_sysmem.getSize()) {
|
if (mip && mip->_sysmem.getSize()) {
|
||||||
return evalMipHeight(level);
|
return evalMipHeight(level);
|
||||||
}
|
}
|
||||||
|
@ -299,24 +364,24 @@ uint16 Texture::getStoredMipHeight(uint16 level) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Texture::getStoredMipDepth(uint16 level) const {
|
uint16 Texture::getStoredMipDepth(uint16 level) const {
|
||||||
PixelsPointer mip = accessStoredMip(level);
|
PixelsPointer mipFace = accessStoredMipFace(level);
|
||||||
if (mip && mip->_sysmem.getSize()) {
|
if (mipFace && mipFace->_sysmem.getSize()) {
|
||||||
return evalMipDepth(level);
|
return evalMipDepth(level);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Texture::getStoredMipNumTexels(uint16 level) const {
|
uint32 Texture::getStoredMipNumTexels(uint16 level) const {
|
||||||
PixelsPointer mip = accessStoredMip(level);
|
PixelsPointer mipFace = accessStoredMipFace(level);
|
||||||
if (mip && mip->_sysmem.getSize()) {
|
if (mipFace && mipFace->_sysmem.getSize()) {
|
||||||
return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level);
|
return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Texture::getStoredMipSize(uint16 level) const {
|
uint32 Texture::getStoredMipSize(uint16 level) const {
|
||||||
PixelsPointer mip = accessStoredMip(level);
|
PixelsPointer mipFace = accessStoredMipFace(level);
|
||||||
if (mip && mip->_sysmem.getSize()) {
|
if (mipFace && mipFace->_sysmem.getSize()) {
|
||||||
return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getTexelFormat().getSize();
|
return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getTexelFormat().getSize();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -112,28 +112,6 @@ public:
|
||||||
};
|
};
|
||||||
typedef std::shared_ptr< Pixels > PixelsPointer;
|
typedef std::shared_ptr< Pixels > PixelsPointer;
|
||||||
|
|
||||||
class Storage {
|
|
||||||
public:
|
|
||||||
Storage() {}
|
|
||||||
virtual ~Storage() {}
|
|
||||||
virtual void reset();
|
|
||||||
virtual PixelsPointer editMip(uint16 level);
|
|
||||||
virtual const PixelsPointer getMip(uint16 level) const;
|
|
||||||
virtual Stamp getStamp(uint16 level) const;
|
|
||||||
virtual bool allocateMip(uint16 level);
|
|
||||||
virtual bool assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes);
|
|
||||||
virtual bool isMipAvailable(uint16 level) const;
|
|
||||||
virtual void notifyGPULoaded(uint16 level) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Texture* _texture;
|
|
||||||
std::vector<PixelsPointer> _mips;
|
|
||||||
|
|
||||||
virtual void assignTexture(Texture* tex);
|
|
||||||
|
|
||||||
friend class Texture;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
TEX_1D = 0,
|
TEX_1D = 0,
|
||||||
TEX_2D,
|
TEX_2D,
|
||||||
|
@ -143,6 +121,39 @@ public:
|
||||||
NUM_TYPES,
|
NUM_TYPES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Storage {
|
||||||
|
public:
|
||||||
|
Storage() {}
|
||||||
|
virtual ~Storage() {}
|
||||||
|
virtual void reset();
|
||||||
|
virtual PixelsPointer editMipFace(uint16 level, uint8 face = 0);
|
||||||
|
virtual const PixelsPointer getMipFace(uint16 level, uint8 face = 0) const;
|
||||||
|
virtual bool allocateMip(uint16 level);
|
||||||
|
virtual bool assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes);
|
||||||
|
virtual bool assignMipFaceData(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face);
|
||||||
|
virtual bool isMipAvailable(uint16 level, uint8 face = 0) const;
|
||||||
|
|
||||||
|
Texture::Type getType() const { return _type; }
|
||||||
|
|
||||||
|
Stamp getStamp() const { return _stamp; }
|
||||||
|
Stamp bumpStamp() { return ++_stamp; }
|
||||||
|
protected:
|
||||||
|
Stamp _stamp = 0;
|
||||||
|
Texture* _texture = nullptr;
|
||||||
|
Texture::Type _type = Texture::TEX_2D; // The type of texture is needed to know the number of faces to expect
|
||||||
|
std::vector<std::vector<PixelsPointer>> _mips; // an array of mips, each mip is an array of faces
|
||||||
|
|
||||||
|
virtual void assignTexture(Texture* tex); // Texture storage is pointing to ONE corrresponding Texture.
|
||||||
|
const Texture* getTexture() const { return _texture; }
|
||||||
|
|
||||||
|
friend class Texture;
|
||||||
|
|
||||||
|
// THis should be only called by the Texture from the Backend to notify the storage that the specified mip face pixels
|
||||||
|
// have been uploaded to the GPU memory. IT is possible for the storage to free the system memory then
|
||||||
|
virtual void notifyMipFaceGPULoaded(uint16 level, uint8 face) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static Texture* create1D(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler());
|
static Texture* create1D(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler());
|
||||||
static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height, const Sampler& sampler = Sampler());
|
static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height, const Sampler& sampler = Sampler());
|
||||||
static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, const Sampler& sampler = Sampler());
|
static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, const Sampler& sampler = Sampler());
|
||||||
|
@ -155,7 +166,7 @@ public:
|
||||||
~Texture();
|
~Texture();
|
||||||
|
|
||||||
Stamp getStamp() const { return _stamp; }
|
Stamp getStamp() const { return _stamp; }
|
||||||
Stamp getDataStamp(uint16 level = 0) const { return _storage->getStamp(level); }
|
Stamp getDataStamp() const { return _storage->getStamp(); }
|
||||||
|
|
||||||
// The size in bytes of data stored in the texture
|
// The size in bytes of data stored in the texture
|
||||||
Size getSize() const { return _size; }
|
Size getSize() const { return _size; }
|
||||||
|
@ -214,8 +225,16 @@ public:
|
||||||
uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); }
|
uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); }
|
||||||
uint16 evalMipHeight(uint16 level) const { return std::max(_height >> level, 1); }
|
uint16 evalMipHeight(uint16 level) const { return std::max(_height >> level, 1); }
|
||||||
uint16 evalMipDepth(uint16 level) const { return std::max(_depth >> level, 1); }
|
uint16 evalMipDepth(uint16 level) const { return std::max(_depth >> level, 1); }
|
||||||
uint32 evalMipNumTexels(uint16 level) const { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getNumFaces(); }
|
|
||||||
|
// Size for each face of a mip at a particular level
|
||||||
|
uint32 evalMipFaceNumTexels(uint16 level) const { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); }
|
||||||
|
uint32 evalMipFaceSize(uint16 level) const { return evalMipFaceNumTexels(level) * getTexelFormat().getSize(); }
|
||||||
|
|
||||||
|
// Total size for the mip
|
||||||
|
uint32 evalMipNumTexels(uint16 level) const { return evalMipFaceNumTexels(level) * getNumFaces(); }
|
||||||
uint32 evalMipSize(uint16 level) const { return evalMipNumTexels(level) * getTexelFormat().getSize(); }
|
uint32 evalMipSize(uint16 level) const { return evalMipNumTexels(level) * getTexelFormat().getSize(); }
|
||||||
|
|
||||||
|
uint32 evalStoredMipFaceSize(uint16 level, const Element& format) const { return evalMipFaceNumTexels(level) * format.getSize(); }
|
||||||
uint32 evalStoredMipSize(uint16 level, const Element& format) const { return evalMipNumTexels(level) * format.getSize(); }
|
uint32 evalStoredMipSize(uint16 level, const Element& format) const { return evalMipNumTexels(level) * format.getSize(); }
|
||||||
|
|
||||||
uint32 evalTotalSize() const {
|
uint32 evalTotalSize() const {
|
||||||
|
@ -256,11 +275,11 @@ public:
|
||||||
// Explicitely assign mip data for a certain level
|
// Explicitely assign mip data for a certain level
|
||||||
// If Bytes is NULL then simply allocate the space so mip sysmem can be accessed
|
// If Bytes is NULL then simply allocate the space so mip sysmem can be accessed
|
||||||
bool assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes);
|
bool assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes);
|
||||||
|
bool assignStoredMipFace(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face);
|
||||||
|
|
||||||
// Access the the sub mips
|
// Access the the sub mips
|
||||||
bool isStoredMipAvailable(uint16 level) const { return _storage->isMipAvailable(level); }
|
bool isStoredMipFaceAvailable(uint16 level, uint8 face = 0) const { return _storage->isMipAvailable(level, face); }
|
||||||
const PixelsPointer accessStoredMip(uint16 level) const { return _storage->getMip(level); }
|
const PixelsPointer accessStoredMipFace(uint16 level, uint8 face = 0) const { return _storage->getMipFace(level, face); }
|
||||||
void notifyGPULoaded(uint16 level) const { return _storage->notifyGPULoaded(level); }
|
|
||||||
|
|
||||||
// access sizes for the stored mips
|
// access sizes for the stored mips
|
||||||
uint16 getStoredMipWidth(uint16 level) const;
|
uint16 getStoredMipWidth(uint16 level) const;
|
||||||
|
@ -277,6 +296,9 @@ public:
|
||||||
const Sampler& getSampler() const { return _sampler; }
|
const Sampler& getSampler() const { return _sampler; }
|
||||||
Stamp getSamplerStamp() const { return _samplerStamp; }
|
Stamp getSamplerStamp() const { return _samplerStamp; }
|
||||||
|
|
||||||
|
// Only callable by the Backend
|
||||||
|
void notifyMipFaceGPULoaded(uint16 level, uint8 face) const { return _storage->notifyMipFaceGPULoaded(level, face); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::unique_ptr< Storage > _storage;
|
std::unique_ptr< Storage > _storage;
|
||||||
|
|
||||||
|
@ -310,6 +332,7 @@ protected:
|
||||||
mutable GPUObject* _gpuObject = NULL;
|
mutable GPUObject* _gpuObject = NULL;
|
||||||
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
||||||
GPUObject* getGPUObject() const { return _gpuObject; }
|
GPUObject* getGPUObject() const { return _gpuObject; }
|
||||||
|
|
||||||
friend class Backend;
|
friend class Backend;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,7 @@ void main(void) {
|
||||||
vec3 eyeDir;
|
vec3 eyeDir;
|
||||||
|
|
||||||
<$transformClipToEyeDir(cam, clipDir, eyeDir)$>;
|
<$transformClipToEyeDir(cam, clipDir, eyeDir)$>;
|
||||||
normal = normalize(eyeDir);
|
|
||||||
<$transformEyeToWorldDir(cam, eyeDir, normal)$>;
|
<$transformEyeToWorldDir(cam, eyeDir, normal)$>;
|
||||||
normal = normalize(normal);
|
|
||||||
|
|
||||||
// Position is supposed to cmoe in clip space
|
// Position is supposed to cmoe in clip space
|
||||||
gl_Position = vec4(texcoord.xy, 0.0, 1.0);
|
gl_Position = vec4(texcoord.xy, 0.0, 1.0);
|
||||||
|
|
|
@ -524,10 +524,37 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_type == CUBE_TEXTURE) {
|
if (_type == CUBE_TEXTURE) {
|
||||||
if (_height >= (6 * _width)) {
|
_gpuTexture = gpu::TexturePointer(gpu::Texture::createCube(formatGPU, image.width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)));
|
||||||
_gpuTexture = gpu::TexturePointer(gpu::Texture::createCube(formatGPU, image.width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)));
|
_gpuTexture->autoGenerateMips(-1);
|
||||||
_gpuTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
|
||||||
_gpuTexture->autoGenerateMips(-1);
|
std::vector<QImage> faces;
|
||||||
|
if (_height == (6 * _width)) {
|
||||||
|
int faceWidth = _width;
|
||||||
|
|
||||||
|
faces.push_back(image.copy(QRect(0, 0 * faceWidth, faceWidth, faceWidth)));
|
||||||
|
faces.push_back(image.copy(QRect(0, 1 * faceWidth, faceWidth, faceWidth)));
|
||||||
|
faces.push_back(image.copy(QRect(0, 2 * faceWidth, faceWidth, faceWidth)));
|
||||||
|
faces.push_back(image.copy(QRect(0, 3 * faceWidth, faceWidth, faceWidth)));
|
||||||
|
faces.push_back(image.copy(QRect(0, 4 * faceWidth, faceWidth, faceWidth)));
|
||||||
|
faces.push_back(image.copy(QRect(0, 5 * faceWidth, faceWidth, faceWidth)));
|
||||||
|
} else if ((_height / 3) == (_width / 4)) {
|
||||||
|
int faceWidth = _height / 3;
|
||||||
|
faces.push_back(image.copy(QRect(2 * faceWidth, faceWidth, faceWidth, faceWidth)));
|
||||||
|
faces.push_back(image.copy(QRect(0 * faceWidth, faceWidth, faceWidth, faceWidth)));
|
||||||
|
|
||||||
|
faces.push_back(image.copy(QRect(1 * faceWidth, 0, faceWidth, faceWidth)));
|
||||||
|
faces.push_back(image.copy(QRect(1 * faceWidth, 0 * faceWidth, faceWidth, faceWidth)));
|
||||||
|
|
||||||
|
faces.push_back(image.copy(QRect(3 * faceWidth, faceWidth, faceWidth, faceWidth)));
|
||||||
|
faces.push_back(image.copy(QRect(1 * faceWidth, faceWidth, faceWidth, faceWidth)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (faces.size() == _gpuTexture->getNumFaces()) {
|
||||||
|
int f = 0;
|
||||||
|
for (auto& face : faces) {
|
||||||
|
_gpuTexture->assignStoredMipFace(0, formatMip, face.byteCount(), face.constBits(), f);
|
||||||
|
f++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
||||||
|
|
Loading…
Reference in a new issue