mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 09:24:00 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into line-entity
This commit is contained in:
commit
b484e95b77
16 changed files with 596 additions and 174 deletions
|
@ -3208,6 +3208,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
|
||||
// Background rendering decision
|
||||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||
auto skybox = model::SkyboxPointer();
|
||||
if (skyStage->getBackgroundMode() == model::SunSkyStage::NO_BACKGROUND) {
|
||||
} else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_DOME) {
|
||||
if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
|
||||
|
@ -3255,7 +3256,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
|
||||
}
|
||||
} else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) {
|
||||
auto skybox = skyStage->getSkybox();
|
||||
skybox = skyStage->getSkybox();
|
||||
if (skybox) {
|
||||
gpu::Batch batch;
|
||||
model::Skybox::render(batch, _viewFrustum, *skybox);
|
||||
|
@ -3334,6 +3335,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity());
|
||||
DependencyManager::get<DeferredLightingEffect>()->setGlobalAtmosphere(skyStage->getAtmosphere());
|
||||
// NOt yet DependencyManager::get<DeferredLightingEffect>()->setGlobalSkybox(skybox);
|
||||
|
||||
PROFILE_RANGE("DeferredLighting");
|
||||
PerformanceTimer perfTimer("lighting");
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<@if GLPROFILE == PC_GL @>
|
||||
<@def GPU_FEATURE_PROFILE GPU_CORE@>
|
||||
<@def GPU_TRANSFORM_PROFILE GPU_CORE@>
|
||||
<@def VERSION_HEADER #version 330 compatibility@>
|
||||
<@def VERSION_HEADER #version 430 compatibility@>
|
||||
<@elif GLPROFILE == MAC_GL @>
|
||||
<@def GPU_FEATURE_PROFILE GPU_LEGACY@>
|
||||
<@def GPU_TRANSFORM_PROFILE GPU_LEGACY@>
|
||||
|
|
|
@ -295,8 +295,8 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
|||
glBindTexture(GL_TEXTURE_2D, object->_texture);
|
||||
|
||||
if (needUpdate) {
|
||||
if (texture.isStoredMipAvailable(0)) {
|
||||
Texture::PixelsPointer mip = texture.accessStoredMip(0);
|
||||
if (texture.isStoredMipFaceAvailable(0)) {
|
||||
Texture::PixelsPointer mip = texture.accessStoredMipFace(0);
|
||||
const GLvoid* bytes = mip->_sysmem.read<Byte>();
|
||||
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
|
||||
texture.notifyGPULoaded(0);
|
||||
texture.notifyMipFaceGPULoaded(0, 0);
|
||||
|
||||
object->_contentStamp = texture.getDataStamp();
|
||||
}
|
||||
} else {
|
||||
const GLvoid* bytes = 0;
|
||||
Element srcFormat = texture.getTexelFormat();
|
||||
if (texture.isStoredMipAvailable(0)) {
|
||||
Texture::PixelsPointer mip = texture.accessStoredMip(0);
|
||||
if (texture.isStoredMipFaceAvailable(0)) {
|
||||
Texture::PixelsPointer mip = texture.accessStoredMipFace(0);
|
||||
|
||||
bytes = mip->_sysmem.read<Byte>();
|
||||
srcFormat = mip->_format;
|
||||
|
@ -352,10 +352,11 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
|||
|
||||
syncSampler(texture.getSampler(), texture.getType(), object);
|
||||
|
||||
// At this point the mip piels have been loaded, we can notify
|
||||
texture.notifyGPULoaded(0);
|
||||
// At this point the mip pixels have been loaded, we can notify
|
||||
texture.notifyMipFaceGPULoaded(0, 0);
|
||||
|
||||
object->_storageStamp = texture.getStamp();
|
||||
object->_contentStamp = texture.getDataStamp();
|
||||
object->_size = texture.getSize();
|
||||
}
|
||||
|
||||
|
@ -370,63 +371,57 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
|||
glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture);
|
||||
const int NUM_FACES = 6;
|
||||
const GLenum FACE_LAYOUT[] = {
|
||||
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 };
|
||||
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 (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);
|
||||
|
||||
// transfer pixels from each faces
|
||||
for (int f = 0; f < NUM_FACES; f++) {
|
||||
glTexImage2D(FACE_LAYOUT[f], 0, texelFormat.internalFormat, width, width, 0,
|
||||
texelFormat.format, texelFormat.type, (GLvoid*) (bytes + f * faceSize));
|
||||
if (texture.isStoredMipFaceAvailable(0, f)) {
|
||||
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);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
} else {
|
||||
|
@ -438,10 +433,8 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
|||
|
||||
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->_contentStamp = texture.getDataStamp();
|
||||
object->_size = texture.getSize();
|
||||
}
|
||||
|
||||
|
|
|
@ -28,69 +28,103 @@ Texture::Pixels::~Pixels() {
|
|||
|
||||
void Texture::Storage::assignTexture(Texture* texture) {
|
||||
_texture = texture;
|
||||
}
|
||||
|
||||
Stamp Texture::Storage::getStamp(uint16 level) const {
|
||||
PixelsPointer mip = getMip(level);
|
||||
if (mip) {
|
||||
return mip->_sysmem.getStamp();
|
||||
if (_texture) {
|
||||
_type = _texture->getType();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Texture::Storage::reset() {
|
||||
_mips.clear();
|
||||
bumpStamp();
|
||||
}
|
||||
|
||||
Texture::PixelsPointer Texture::Storage::editMip(uint16 level) {
|
||||
Texture::PixelsPointer Texture::Storage::editMipFace(uint16 level, uint8 face) {
|
||||
if (level < _mips.size()) {
|
||||
return _mips[level];
|
||||
assert(face < _mips[level].size());
|
||||
bumpStamp();
|
||||
return _mips[level][face];
|
||||
}
|
||||
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()) {
|
||||
return _mips[level];
|
||||
assert(face < _mips[level].size());
|
||||
return _mips[level][face];
|
||||
}
|
||||
return PixelsPointer();
|
||||
}
|
||||
|
||||
void Texture::Storage::notifyGPULoaded(uint16 level) const {
|
||||
PixelsPointer mip = getMip(level);
|
||||
if (mip) {
|
||||
mip->_isGPULoaded = true;
|
||||
mip->_sysmem.resize(0);
|
||||
void Texture::Storage::notifyMipFaceGPULoaded(uint16 level, uint8 face) const {
|
||||
PixelsPointer mipFace = getMipFace(level, face);
|
||||
if (mipFace) {
|
||||
mipFace->_isGPULoaded = true;
|
||||
mipFace->_sysmem.resize(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool Texture::Storage::isMipAvailable(uint16 level) const {
|
||||
PixelsPointer mip = getMip(level);
|
||||
return (mip && mip->_sysmem.getSize());
|
||||
bool Texture::Storage::isMipAvailable(uint16 level, uint8 face) const {
|
||||
PixelsPointer mipFace = getMipFace(level, face);
|
||||
return (mipFace && mipFace->_sysmem.getSize());
|
||||
}
|
||||
|
||||
bool Texture::Storage::allocateMip(uint16 level) {
|
||||
bool changed = false;
|
||||
if (level >= _mips.size()) {
|
||||
_mips.resize(level+1, PixelsPointer());
|
||||
_mips.resize(level+1, std::vector<PixelsPointer>(Texture::NUM_FACES_PER_TYPE[getType()]));
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (!_mips[level]) {
|
||||
_mips[level] = PixelsPointer(new Pixels());
|
||||
changed = true;
|
||||
auto& mip = _mips[level];
|
||||
for (auto& face : mip) {
|
||||
if (!face) {
|
||||
face.reset(new Pixels());
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
bumpStamp();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
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);
|
||||
auto mip = _mips[level];
|
||||
mip->_format = format;
|
||||
Size allocated = mip->_sysmem.setData(size, bytes);
|
||||
mip->_isGPULoaded = false;
|
||||
Size allocated = 0;
|
||||
if (face < mip.size()) {
|
||||
auto mipFace = mip[face];
|
||||
mipFace->_format = format;
|
||||
allocated += mipFace->_sysmem.setData(size, bytes);
|
||||
mipFace->_isGPULoaded = false;
|
||||
bumpStamp();
|
||||
}
|
||||
|
||||
return allocated == size;
|
||||
}
|
||||
|
@ -115,8 +149,8 @@ Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, ui
|
|||
{
|
||||
Texture* tex = new Texture();
|
||||
tex->_storage.reset(new Storage());
|
||||
tex->_storage->_texture = tex;
|
||||
tex->_type = type;
|
||||
tex->_storage->assignTexture(tex);
|
||||
tex->_maxMip = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
_autoGenerateMips = true;
|
||||
_maxMip = std::min((uint16) (evalNumMips() - 1), maxMip);
|
||||
|
@ -283,15 +348,15 @@ uint16 Texture::autoGenerateMips(uint16 maxMip) {
|
|||
}
|
||||
|
||||
uint16 Texture::getStoredMipWidth(uint16 level) const {
|
||||
PixelsPointer mip = accessStoredMip(level);
|
||||
if (mip && mip->_sysmem.getSize()) {
|
||||
PixelsPointer mipFace = accessStoredMipFace(level);
|
||||
if (mipFace && mipFace->_sysmem.getSize()) {
|
||||
return evalMipWidth(level);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 Texture::getStoredMipHeight(uint16 level) const {
|
||||
PixelsPointer mip = accessStoredMip(level);
|
||||
PixelsPointer mip = accessStoredMipFace(level);
|
||||
if (mip && mip->_sysmem.getSize()) {
|
||||
return evalMipHeight(level);
|
||||
}
|
||||
|
@ -299,24 +364,24 @@ uint16 Texture::getStoredMipHeight(uint16 level) const {
|
|||
}
|
||||
|
||||
uint16 Texture::getStoredMipDepth(uint16 level) const {
|
||||
PixelsPointer mip = accessStoredMip(level);
|
||||
if (mip && mip->_sysmem.getSize()) {
|
||||
PixelsPointer mipFace = accessStoredMipFace(level);
|
||||
if (mipFace && mipFace->_sysmem.getSize()) {
|
||||
return evalMipDepth(level);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 Texture::getStoredMipNumTexels(uint16 level) const {
|
||||
PixelsPointer mip = accessStoredMip(level);
|
||||
if (mip && mip->_sysmem.getSize()) {
|
||||
PixelsPointer mipFace = accessStoredMipFace(level);
|
||||
if (mipFace && mipFace->_sysmem.getSize()) {
|
||||
return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 Texture::getStoredMipSize(uint16 level) const {
|
||||
PixelsPointer mip = accessStoredMip(level);
|
||||
if (mip && mip->_sysmem.getSize()) {
|
||||
PixelsPointer mipFace = accessStoredMipFace(level);
|
||||
if (mipFace && mipFace->_sysmem.getSize()) {
|
||||
return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getTexelFormat().getSize();
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -112,28 +112,6 @@ public:
|
|||
};
|
||||
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 {
|
||||
TEX_1D = 0,
|
||||
TEX_2D,
|
||||
|
@ -143,6 +121,51 @@ public:
|
|||
NUM_TYPES,
|
||||
};
|
||||
|
||||
// Definition of the cube face name and layout
|
||||
enum CubeFace {
|
||||
CUBE_FACE_RIGHT_POS_X = 0,
|
||||
CUBE_FACE_LEFT_NEG_X,
|
||||
CUBE_FACE_TOP_POS_Y,
|
||||
CUBE_FACE_BOTTOM_NEG_Y,
|
||||
CUBE_FACE_BACK_POS_X,
|
||||
CUBE_FACE_FRONT_NEG_Z,
|
||||
|
||||
NUM_CUBE_FACES, // Not a valid vace index
|
||||
};
|
||||
|
||||
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* 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());
|
||||
|
@ -155,7 +178,7 @@ public:
|
|||
~Texture();
|
||||
|
||||
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
|
||||
Size getSize() const { return _size; }
|
||||
|
@ -214,8 +237,16 @@ public:
|
|||
uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); }
|
||||
uint16 evalMipHeight(uint16 level) const { return std::max(_height >> 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 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 evalTotalSize() const {
|
||||
|
@ -256,11 +287,11 @@ public:
|
|||
// Explicitely assign mip data for a certain level
|
||||
// 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 assignStoredMipFace(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face);
|
||||
|
||||
// Access the the sub mips
|
||||
bool isStoredMipAvailable(uint16 level) const { return _storage->isMipAvailable(level); }
|
||||
const PixelsPointer accessStoredMip(uint16 level) const { return _storage->getMip(level); }
|
||||
void notifyGPULoaded(uint16 level) const { return _storage->notifyGPULoaded(level); }
|
||||
bool isStoredMipFaceAvailable(uint16 level, uint8 face = 0) const { return _storage->isMipAvailable(level, face); }
|
||||
const PixelsPointer accessStoredMipFace(uint16 level, uint8 face = 0) const { return _storage->getMipFace(level, face); }
|
||||
|
||||
// access sizes for the stored mips
|
||||
uint16 getStoredMipWidth(uint16 level) const;
|
||||
|
@ -277,6 +308,9 @@ public:
|
|||
const Sampler& getSampler() const { return _sampler; }
|
||||
Stamp getSamplerStamp() const { return _samplerStamp; }
|
||||
|
||||
// Only callable by the Backend
|
||||
void notifyMipFaceGPULoaded(uint16 level, uint8 face) const { return _storage->notifyMipFaceGPULoaded(level, face); }
|
||||
|
||||
protected:
|
||||
std::unique_ptr< Storage > _storage;
|
||||
|
||||
|
@ -310,6 +344,7 @@ protected:
|
|||
mutable GPUObject* _gpuObject = NULL;
|
||||
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
||||
GPUObject* getGPUObject() const { return _gpuObject; }
|
||||
|
||||
friend class Backend;
|
||||
};
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
static gpu::PipelinePointer thePipeline;
|
||||
static gpu::BufferPointer theBuffer;
|
||||
static gpu::Stream::FormatPointer theFormat;
|
||||
static gpu::BufferPointer theConstants;
|
||||
int SKYBOX_CONSTANTS_SLOT = 0; // need to be defined by the compilation of the shader
|
||||
if (!thePipeline) {
|
||||
auto skyVS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(Skybox_vert)));
|
||||
auto skyFS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(Skybox_frag)));
|
||||
|
@ -59,11 +61,15 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
|
||||
gpu::Shader::BindingSet bindings;
|
||||
bindings.insert(gpu::Shader::Binding(std::string("cubeMap"), 0));
|
||||
|
||||
if (!gpu::Shader::makeProgram(*skyShader, bindings)) {
|
||||
|
||||
}
|
||||
|
||||
SKYBOX_CONSTANTS_SLOT = skyShader->getBuffers().findLocation("skyboxBuffer");
|
||||
if (SKYBOX_CONSTANTS_SLOT == gpu::Shader::INVALID_LOCATION) {
|
||||
SKYBOX_CONSTANTS_SLOT = skyShader->getUniforms().findLocation("skyboxBuffer");
|
||||
}
|
||||
|
||||
auto skyState = gpu::StatePointer(new gpu::State());
|
||||
|
||||
thePipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState));
|
||||
|
@ -74,6 +80,9 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
|
||||
theFormat.reset(new gpu::Stream::Format());
|
||||
theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ));
|
||||
|
||||
auto color = glm::vec4(1.0f);
|
||||
theConstants.reset(new gpu::Buffer(sizeof(color), (const gpu::Byte*) &color));
|
||||
}
|
||||
|
||||
glm::mat4 projMat;
|
||||
|
@ -82,11 +91,19 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
Transform viewTransform;
|
||||
viewFrustum.evalViewTransform(viewTransform);
|
||||
|
||||
if (glm::all(glm::equal(skybox.getColor(), glm::vec3(0.0f)))) {
|
||||
auto color = glm::vec4(1.0f);
|
||||
theConstants->setSubData(0, sizeof(color), (const gpu::Byte*) &color);
|
||||
} else {
|
||||
theConstants->setSubData(0, sizeof(Color), (const gpu::Byte*) &skybox.getColor());
|
||||
}
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewTransform);
|
||||
batch.setModelTransform(Transform()); // only for Mac
|
||||
batch.setPipeline(thePipeline);
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8);
|
||||
batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, theConstants, 0, theConstants->getSize());
|
||||
batch.setInputFormat(theFormat);
|
||||
batch.setUniformTexture(0, skybox.getCubemap());
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
|
||||
protected:
|
||||
gpu::TexturePointer _cubemap;
|
||||
|
||||
Color _color{1.0f, 1.0f, 1.0f};
|
||||
};
|
||||
typedef std::shared_ptr< Skybox > SkyboxPointer;
|
||||
|
|
|
@ -20,6 +20,5 @@ varying vec3 color;
|
|||
void main(void) {
|
||||
vec3 coord = normalize(normal);
|
||||
vec4 texel = textureCube(cubeMap, coord);
|
||||
// gl_FragData[0] = vec4(texel.xyz * color, texel.w);
|
||||
gl_FragData[0] = vec4(texel.xyz, 1.0);
|
||||
gl_FragData[0] = vec4(texel.xyz * color, 0.0);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,26 @@
|
|||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
struct Skybox {
|
||||
vec4 _color;
|
||||
};
|
||||
|
||||
<@if GPU_FEATURE_PROFILE == GPU_CORE @>
|
||||
uniform skyboxBuffer {
|
||||
Skybox _skybox;
|
||||
};
|
||||
Skybox getSkybox() {
|
||||
return _skybox;
|
||||
}
|
||||
<@else@>
|
||||
uniform vec4 skyboxBuffer[1];
|
||||
Skybox getSkybox() {
|
||||
Skybox _skybox;
|
||||
_skybox._color = skyboxBuffer[0];
|
||||
return _skybox;
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
varying vec3 normal;
|
||||
varying vec2 texcoord;
|
||||
varying vec3 color;
|
||||
|
@ -22,8 +42,8 @@ varying vec3 color;
|
|||
void main(void) {
|
||||
texcoord = gl_Vertex.xy;
|
||||
|
||||
// pass along the diffuse color
|
||||
color = vec3(texcoord, 0.0);
|
||||
Skybox skybox = getSkybox();
|
||||
color = skybox._color.xyz;
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
|
@ -31,9 +51,7 @@ void main(void) {
|
|||
vec3 eyeDir;
|
||||
|
||||
<$transformClipToEyeDir(cam, clipDir, eyeDir)$>;
|
||||
normal = normalize(eyeDir);
|
||||
<$transformEyeToWorldDir(cam, eyeDir, normal)$>;
|
||||
normal = normalize(normal);
|
||||
|
||||
// Position is supposed to cmoe in clip space
|
||||
gl_Position = vec4(texcoord.xy, 0.0, 1.0);
|
||||
|
|
|
@ -13,39 +13,50 @@
|
|||
|
||||
<@include DeferredLighting.slh@>
|
||||
|
||||
uniform samplerCube skyboxMap;
|
||||
|
||||
struct SphericalHarmonics {
|
||||
vec4 L00;
|
||||
vec4 L1m1;
|
||||
vec4 L10;
|
||||
vec4 L11;
|
||||
vec4 L2m2;
|
||||
vec4 L2m1;
|
||||
vec4 L20;
|
||||
vec4 L21;
|
||||
vec4 L22;
|
||||
vec4 evalSkyboxLight(vec3 direction, float lod) {
|
||||
|
||||
<@if GPU_TRANSFORM_PROFILE == GPU_CORE@>
|
||||
vec4 skytexel = textureCubeLod(skyboxMap, direction, lod * textureQueryLevels(skyboxMap));
|
||||
<@else@>
|
||||
vec4 skytexel = textureCube(skyboxMap, direction);
|
||||
<@endif@>
|
||||
return skytexel;
|
||||
}
|
||||
|
||||
struct SphericalHarmonics {
|
||||
vec4 L00;
|
||||
vec4 L1m1;
|
||||
vec4 L10;
|
||||
vec4 L11;
|
||||
vec4 L2m2;
|
||||
vec4 L2m1;
|
||||
vec4 L20;
|
||||
vec4 L21;
|
||||
vec4 L22;
|
||||
};
|
||||
|
||||
vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) {
|
||||
|
||||
vec3 dir = direction.xzy; // we don;t understand why yet but we need to use z as vertical axis?
|
||||
|
||||
const float C1 = 0.429043;
|
||||
const float C2 = 0.511664;
|
||||
const float C3 = 0.743125;
|
||||
const float C4 = 0.886227;
|
||||
const float C5 = 0.247708;
|
||||
|
||||
vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +
|
||||
C3 * sh.L20 * dir.z * dir.z +
|
||||
C4 * sh.L00 - C5 * sh.L20 +
|
||||
2.0 * C1 * ( sh.L2m2 * dir.x * dir.y +
|
||||
sh.L21 * dir.x * dir.z +
|
||||
sh.L2m1 * dir.y * dir.z ) +
|
||||
2.0 * C2 * ( sh.L11 * dir.x +
|
||||
sh.L1m1 * dir.y +
|
||||
sh.L10 * dir.z ) ;
|
||||
return value;
|
||||
|
||||
vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) {
|
||||
|
||||
vec3 dir = direction.xzy; // we don;t understand why yet but we need to use z as vertical axis?
|
||||
|
||||
const float C1 = 0.429043;
|
||||
const float C2 = 0.511664;
|
||||
const float C3 = 0.743125;
|
||||
const float C4 = 0.886227;
|
||||
const float C5 = 0.247708;
|
||||
|
||||
vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) +
|
||||
C3 * sh.L20 * dir.z * dir.z +
|
||||
C4 * sh.L00 - C5 * sh.L20 +
|
||||
2.0 * C1 * ( sh.L2m2 * dir.x * dir.y +
|
||||
sh.L21 * dir.x * dir.z +
|
||||
sh.L2m1 * dir.y * dir.z ) +
|
||||
2.0 * C2 * ( sh.L11 * dir.x +
|
||||
sh.L1m1 * dir.y +
|
||||
sh.L10 * dir.z ) ;
|
||||
return value;
|
||||
}
|
||||
|
||||
// Need one SH
|
||||
|
@ -92,6 +103,23 @@ vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 no
|
|||
return color;
|
||||
}
|
||||
|
||||
vec3 evalSkyboxGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
|
||||
// Need the light now
|
||||
Light light = getLight();
|
||||
|
||||
vec3 fragNormal = normalize(vec3(invViewMat * vec4(normal, 0.0)));
|
||||
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
|
||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||
|
||||
vec3 color = diffuse.rgb * evalSkyboxLight(fragNormal, 0.75).xyz * getLightAmbientIntensity(light);
|
||||
|
||||
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
|
||||
|
||||
color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) {
|
||||
|
||||
Light light = getLight();
|
||||
|
|
|
@ -41,6 +41,10 @@
|
|||
#include "directional_ambient_light_shadow_map_frag.h"
|
||||
#include "directional_ambient_light_cascaded_shadow_map_frag.h"
|
||||
|
||||
#include "directional_skybox_light_frag.h"
|
||||
#include "directional_skybox_light_shadow_map_frag.h"
|
||||
#include "directional_skybox_light_cascaded_shadow_map_frag.h"
|
||||
|
||||
#include "point_light_frag.h"
|
||||
#include "spot_light_frag.h"
|
||||
|
||||
|
@ -66,6 +70,12 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
|
|||
loadLightProgram(directional_ambient_light_cascaded_shadow_map_frag, false, _directionalAmbientSphereLightCascadedShadowMap,
|
||||
_directionalAmbientSphereLightCascadedShadowMapLocations);
|
||||
|
||||
loadLightProgram(directional_skybox_light_frag, false, _directionalSkyboxLight, _directionalSkyboxLightLocations);
|
||||
loadLightProgram(directional_skybox_light_shadow_map_frag, false, _directionalSkyboxLightShadowMap,
|
||||
_directionalSkyboxLightShadowMapLocations);
|
||||
loadLightProgram(directional_skybox_light_cascaded_shadow_map_frag, false, _directionalSkyboxLightCascadedShadowMap,
|
||||
_directionalSkyboxLightCascadedShadowMapLocations);
|
||||
|
||||
loadLightProgram(point_light_frag, true, _pointLight, _pointLightLocations);
|
||||
loadLightProgram(spot_light_frag, true, _spotLight, _spotLightLocations);
|
||||
|
||||
|
@ -217,6 +227,7 @@ void DeferredLightingEffect::render() {
|
|||
float tMin = viewport[VIEWPORT_Y_INDEX] / (float)framebufferSize.height();
|
||||
float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)framebufferSize.height();
|
||||
|
||||
bool useSkyboxCubemap = (_skybox) && (_skybox->getCubemap());
|
||||
|
||||
// Fetch the ViewMatrix;
|
||||
glm::mat4 invViewMat;
|
||||
|
@ -234,7 +245,10 @@ void DeferredLightingEffect::render() {
|
|||
if (_viewState->getCascadeShadowsEnabled()) {
|
||||
program = &_directionalLightCascadedShadowMap;
|
||||
locations = &_directionalLightCascadedShadowMapLocations;
|
||||
if (_ambientLightMode > -1) {
|
||||
if (useSkyboxCubemap) {
|
||||
program = &_directionalSkyboxLightCascadedShadowMap;
|
||||
locations = &_directionalSkyboxLightCascadedShadowMapLocations;
|
||||
} else if (_ambientLightMode > -1) {
|
||||
program = &_directionalAmbientSphereLightCascadedShadowMap;
|
||||
locations = &_directionalAmbientSphereLightCascadedShadowMapLocations;
|
||||
}
|
||||
|
@ -242,7 +256,10 @@ void DeferredLightingEffect::render() {
|
|||
program->setUniform(locations->shadowDistances, _viewState->getShadowDistances());
|
||||
|
||||
} else {
|
||||
if (_ambientLightMode > -1) {
|
||||
if (useSkyboxCubemap) {
|
||||
program = &_directionalSkyboxLightShadowMap;
|
||||
locations = &_directionalSkyboxLightShadowMapLocations;
|
||||
} else if (_ambientLightMode > -1) {
|
||||
program = &_directionalAmbientSphereLightShadowMap;
|
||||
locations = &_directionalAmbientSphereLightShadowMapLocations;
|
||||
}
|
||||
|
@ -252,7 +269,10 @@ void DeferredLightingEffect::render() {
|
|||
1.0f / textureCache->getShadowFramebuffer()->getWidth());
|
||||
|
||||
} else {
|
||||
if (_ambientLightMode > -1) {
|
||||
if (useSkyboxCubemap) {
|
||||
program = &_directionalSkyboxLight;
|
||||
locations = &_directionalSkyboxLightLocations;
|
||||
} else if (_ambientLightMode > -1) {
|
||||
program = &_directionalAmbientSphereLight;
|
||||
locations = &_directionalAmbientSphereLightLocations;
|
||||
}
|
||||
|
@ -269,6 +289,11 @@ void DeferredLightingEffect::render() {
|
|||
}
|
||||
}
|
||||
|
||||
if (useSkyboxCubemap) {
|
||||
glActiveTexture(GL_TEXTURE5);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, gpu::GLBackend::getTextureID(_skybox->getCubemap()));
|
||||
}
|
||||
|
||||
if (locations->lightBufferUnit >= 0) {
|
||||
gpu::Batch batch;
|
||||
batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer());
|
||||
|
@ -300,7 +325,14 @@ void DeferredLightingEffect::render() {
|
|||
renderFullscreenQuad(sMin, sMin + sWidth, tMin, tMin + tHeight);
|
||||
|
||||
program->release();
|
||||
|
||||
|
||||
if (useSkyboxCubemap) {
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
if (!shadowsEnabled) {
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
}
|
||||
}
|
||||
|
||||
if (shadowsEnabled) {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
|
@ -492,6 +524,7 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit
|
|||
program.setUniformValue("specularMap", 2);
|
||||
program.setUniformValue("depthMap", 3);
|
||||
program.setUniformValue("shadowMap", 4);
|
||||
program.setUniformValue("skyboxMap", 5);
|
||||
locations.shadowDistances = program.uniformLocation("shadowDistances");
|
||||
locations.shadowScale = program.uniformLocation("shadowScale");
|
||||
locations.nearLocation = program.uniformLocation("near");
|
||||
|
|
|
@ -101,6 +101,13 @@ private:
|
|||
ProgramObject _simpleProgram;
|
||||
int _glowIntensityLocation;
|
||||
|
||||
ProgramObject _directionalSkyboxLight;
|
||||
LightLocations _directionalSkyboxLightLocations;
|
||||
ProgramObject _directionalSkyboxLightShadowMap;
|
||||
LightLocations _directionalSkyboxLightShadowMapLocations;
|
||||
ProgramObject _directionalSkyboxLightCascadedShadowMap;
|
||||
LightLocations _directionalSkyboxLightCascadedShadowMapLocations;
|
||||
|
||||
ProgramObject _directionalAmbientSphereLight;
|
||||
LightLocations _directionalAmbientSphereLightLocations;
|
||||
ProgramObject _directionalAmbientSphereLightShadowMap;
|
||||
|
|
|
@ -513,7 +513,7 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo
|
|||
imageLoaded(image);
|
||||
|
||||
if ((_width > 0) && (_height > 0)) {
|
||||
|
||||
|
||||
bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
|
||||
|
||||
gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
|
||||
|
@ -524,10 +524,94 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo
|
|||
}
|
||||
|
||||
if (_type == CUBE_TEXTURE) {
|
||||
if (_height >= (6 * _width)) {
|
||||
_gpuTexture = gpu::TexturePointer(gpu::Texture::createCube(formatGPU, image.width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP)));
|
||||
_gpuTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
||||
|
||||
std::vector<QImage> faces;
|
||||
if (_height == (6 * _width)) {
|
||||
int faceWidth = _width;
|
||||
|
||||
// Here is the expected layout for the faces in an image with the 1/6 aspect ratio:
|
||||
//
|
||||
// WIDTH
|
||||
// <------>
|
||||
// ^ +------+
|
||||
// | | |
|
||||
// | | +X |
|
||||
// | | |
|
||||
// H +------+
|
||||
// E | |
|
||||
// I | -X |
|
||||
// G | |
|
||||
// H +------+
|
||||
// T | |
|
||||
// | | +Y |
|
||||
// | | |
|
||||
// | +------+
|
||||
// | | |
|
||||
// | | -Y |
|
||||
// | | |
|
||||
// H +------+
|
||||
// E | |
|
||||
// I | +Z |
|
||||
// G | |
|
||||
// H +------+
|
||||
// T | |
|
||||
// | | -Z |
|
||||
// | | |
|
||||
// V +------+
|
||||
//
|
||||
// FaceWidth = width = height / 6
|
||||
|
||||
faces.push_back(image.copy(QRect(0, 0 * faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
faces.push_back(image.copy(QRect(0, 1 * faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
faces.push_back(image.copy(QRect(0, 2 * faceWidth, faceWidth, faceWidth)).mirrored(false, true));
|
||||
faces.push_back(image.copy(QRect(0, 3 * faceWidth, faceWidth, faceWidth)).mirrored(false, true));
|
||||
faces.push_back(image.copy(QRect(0, 4 * faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
faces.push_back(image.copy(QRect(0, 5 * faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
|
||||
} else if ((_height / 3) == (_width / 4)) {
|
||||
int faceWidth = _height / 3;
|
||||
|
||||
// Here is the expected layout for the faces in an image with the 3/4 aspect ratio:
|
||||
//
|
||||
// <-----------WIDTH----------->
|
||||
// ^ +------+------+------+------+
|
||||
// | | | | | |
|
||||
// | | | +Y | | |
|
||||
// | | | | | |
|
||||
// H +------+------+------+------+
|
||||
// E | | | | |
|
||||
// I | -X | -Z | +X | +Z |
|
||||
// G | | | | |
|
||||
// H +------+------+------+------+
|
||||
// T | | | | |
|
||||
// | | | -Y | | |
|
||||
// | | | | | |
|
||||
// V +------+------+------+------+
|
||||
//
|
||||
// FaceWidth = width / 4 = height / 3
|
||||
|
||||
// Right = +X
|
||||
faces.push_back(image.copy(QRect(2 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
// Left = -X
|
||||
faces.push_back(image.copy(QRect(0 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
// Top = +Y
|
||||
faces.push_back(image.copy(QRect(1 * faceWidth, 0, faceWidth, faceWidth)).mirrored(false, true));
|
||||
// Bottom = -Y
|
||||
faces.push_back(image.copy(QRect(1 * faceWidth, 2 * faceWidth, faceWidth, faceWidth)).mirrored(false, true));
|
||||
// Back = +Z
|
||||
faces.push_back(image.copy(QRect(3 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
// Front = -Z
|
||||
faces.push_back(image.copy(QRect(1 * faceWidth, faceWidth, faceWidth, faceWidth)).mirrored(true, false));
|
||||
}
|
||||
|
||||
if (faces.size() == gpu::Texture::NUM_FACES_PER_TYPE[gpu::Texture::TEX_CUBE]) {
|
||||
_gpuTexture = gpu::TexturePointer(gpu::Texture::createCube(formatGPU, faces[0].width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP)));
|
||||
_gpuTexture->autoGenerateMips(-1);
|
||||
int f = 0;
|
||||
for (auto& face : faces) {
|
||||
_gpuTexture->assignStoredMipFace(0, formatMip, face.byteCount(), face.constBits(), f);
|
||||
f++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
||||
|
|
43
libraries/render-utils/src/directional_skybox_light.slf
Executable file
43
libraries/render-utils/src/directional_skybox_light.slf
Executable file
|
@ -0,0 +1,43 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// directional_light.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Sam Gateau on 5/8/2015.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// Everything about deferred buffer
|
||||
<@include DeferredBuffer.slh@>
|
||||
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
void main(void) {
|
||||
DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st);
|
||||
|
||||
|
||||
// Light mapped or not ?
|
||||
if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) {
|
||||
vec3 color = evalLightmappedColor(
|
||||
1.0,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
frag.specularVal.xyz);
|
||||
|
||||
gl_FragColor = vec4(color, 1.0);
|
||||
} else {
|
||||
vec3 color = evalSkyboxGlobalColor(1.0,
|
||||
frag.position.xyz,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
frag.specular,
|
||||
frag.gloss);
|
||||
|
||||
gl_FragColor = vec4(color, frag.normalVal.a);
|
||||
}
|
||||
}
|
48
libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf
Executable file
48
libraries/render-utils/src/directional_skybox_light_cascaded_shadow_map.slf
Executable file
|
@ -0,0 +1,48 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// directional_light.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Sam Gateau on 5/8/2015.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// Everything about deferred buffer
|
||||
<@include DeferredBuffer.slh@>
|
||||
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
// Everything about shadow
|
||||
<@include Shadow.slh@>
|
||||
|
||||
void main(void) {
|
||||
DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st);
|
||||
|
||||
// Eval shadow Texcoord and then Attenuation
|
||||
vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position);
|
||||
float shadowAttenuation = evalShadowAttenuation(shadowTexcoord);
|
||||
|
||||
// Light mapped or not ?
|
||||
if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) {
|
||||
gl_FragColor = vec4(evalLightmappedColor(
|
||||
shadowAttenuation,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
frag.specularVal.xyz),
|
||||
1.0);
|
||||
} else {
|
||||
vec3 color = evalSkyboxGlobalColor(shadowAttenuation,
|
||||
frag.position.xyz,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
frag.specular,
|
||||
frag.gloss);
|
||||
|
||||
gl_FragColor = vec4(color, frag.normalVal.a);
|
||||
}
|
||||
}
|
49
libraries/render-utils/src/directional_skybox_light_shadow_map.slf
Executable file
49
libraries/render-utils/src/directional_skybox_light_shadow_map.slf
Executable file
|
@ -0,0 +1,49 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// directional_light.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Sam Gateau on 5/8/2015.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// Everything about deferred buffer
|
||||
<@include DeferredBuffer.slh@>
|
||||
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
// Everything about shadow
|
||||
<@include Shadow.slh@>
|
||||
|
||||
|
||||
void main(void) {
|
||||
DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st);
|
||||
|
||||
// Eval shadow Texcoord and then Attenuation
|
||||
vec4 shadowTexcoord = evalShadowTexcoord(frag.position);
|
||||
float shadowAttenuation = evalShadowAttenuation(shadowTexcoord);
|
||||
|
||||
// Light mapped or not ?
|
||||
if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) {
|
||||
gl_FragColor = vec4(evalLightmappedColor(
|
||||
shadowAttenuation,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
frag.specularVal.xyz),
|
||||
1.0);
|
||||
} else {
|
||||
vec3 color = evalSkyboxGlobalColor(shadowAttenuation,
|
||||
frag.position.xyz,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
frag.specular,
|
||||
frag.gloss);
|
||||
|
||||
gl_FragColor = vec4(color, frag.normalVal.a);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue