From fcd58bb373dd6c51d7ee557b50f3bddd1b90f8cd Mon Sep 17 00:00:00 2001 From: kearwood Date: Sat, 6 Oct 2012 01:43:11 +0000 Subject: [PATCH] Implementation of reflections in progress --HG-- extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%40124 --- KREngine/KREngine/Classes/KRMaterial.cpp | 14 ++- KREngine/KREngine/Classes/KRMaterial.h | 3 + .../KREngine/Classes/KRMaterialManager.cpp | 3 +- KREngine/KREngine/Classes/KRTexture.cpp | 50 ++++++++- KREngine/KREngine/Classes/KRTexture.h | 24 ++-- KREngine/KREngine/Classes/KRTexture2D.cpp | 104 ++++++++---------- KREngine/KREngine/Classes/KRTexture2D.h | 24 ++-- KREngine/KREngine/Classes/KRTextureCube.cpp | 55 ++++++--- KREngine/KREngine/Classes/KRTextureCube.h | 36 ++++-- .../KREngine/Classes/KRTextureManager.cpp | 19 ++-- KREngine/KREngine/Classes/KRTextureManager.h | 3 +- 11 files changed, 209 insertions(+), 126 deletions(-) diff --git a/KREngine/KREngine/Classes/KRMaterial.cpp b/KREngine/KREngine/Classes/KRMaterial.cpp index 23c4dfd..fbd5735 100644 --- a/KREngine/KREngine/Classes/KRMaterial.cpp +++ b/KREngine/KREngine/Classes/KRMaterial.cpp @@ -6,7 +6,7 @@ // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // @@ -46,6 +46,7 @@ KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(cont m_pSpecularMap = NULL; m_pNormalMap = NULL; m_pReflectionMap = NULL; + m_pReflectionCube = NULL; m_ambientColor = KRVector3::Zero(); m_diffuseColor = KRVector3::One(); m_specularColor = KRVector3::One(); @@ -57,6 +58,7 @@ KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(cont m_specularMap = ""; m_normalMap = ""; m_reflectionMap = ""; + m_reflectionCube = ""; m_ambientMapOffset = KRVector2(0.0f, 0.0f); m_specularMapOffset = KRVector2(0.0f, 0.0f); m_diffuseMapOffset = KRVector2(0.0f, 0.0f); @@ -105,6 +107,9 @@ bool KRMaterial::save(const std::string& path) { if(m_reflectionMap.size()) { fprintf(f, "map_Reflection %s.pvr -s %f %f -o %f %f\n", m_reflectionMap.c_str(), m_reflectionMapScale.x, m_reflectionMapScale.y, m_reflectionMapOffset.x, m_reflectionMapOffset.y); } + if(m_reflectionCube.size()) { + fprintf(f, "map_ReflectionCube %s.pvr\n", m_reflectionCube.c_str()); + } switch(m_alpha_mode) { case KRMATERIAL_ALPHA_MODE_OPAQUE: fprintf(f, "alpha_mode opaque"); @@ -154,6 +159,10 @@ void KRMaterial::setReflectionMap(std::string texture_name, KRVector2 texture_sc m_reflectionMapOffset = texture_offset; } +void KRMaterial::setReflectionCube(std::string texture_name) { + m_reflectionCube = texture_name; +} + void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) { m_alpha_mode = alpha_mode; } @@ -217,6 +226,9 @@ bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, KRC if(!m_pReflectionMap && m_reflectionMap.size()) { m_pReflectionMap = pContext->getTextureManager()->getTexture(m_reflectionMap.c_str()); } + if(!m_pReflectionCube && m_reflectionCube.size()) { + m_pReflectionCube = pContext->getTextureManager()->getTextureCube(m_reflectionCube.c_str()); + } if(!bSameMaterial) { KRVector2 default_scale = KRVector2(1.0f, 1.0f); diff --git a/KREngine/KREngine/Classes/KRMaterial.h b/KREngine/KREngine/Classes/KRMaterial.h index 63b7fe9..6e665f0 100644 --- a/KREngine/KREngine/Classes/KRMaterial.h +++ b/KREngine/KREngine/Classes/KRMaterial.h @@ -73,6 +73,7 @@ public: void setDiffuseMap(std::string texture_name, KRVector2 texture_scale, KRVector2 texture_offset); void setSpecularMap(std::string texture_name, KRVector2 texture_scale, KRVector2 texture_offset); void setReflectionMap(std::string texture_name, KRVector2 texture_scale, KRVector2 texture_offset); + void setReflectionCube(std::string texture_name); void setNormalMap(std::string texture_name, KRVector2 texture_scale, KRVector2 texture_offset); void setAmbient(const KRVector3 &c); void setDiffuse(const KRVector3 &c); @@ -102,11 +103,13 @@ private: KRTexture *m_pDiffuseMap; // mtl map_Kd value KRTexture *m_pSpecularMap; // mtl map_Ks value KRTexture *m_pReflectionMap; // mtl refl value + KRTexture *m_pReflectionCube; KRTexture *m_pNormalMap; // mtl map_Normal value std::string m_ambientMap; std::string m_diffuseMap; std::string m_specularMap; std::string m_reflectionMap; + std::string m_reflectionCube; std::string m_normalMap; KRVector2 m_ambientMapScale; diff --git a/KREngine/KREngine/Classes/KRMaterialManager.cpp b/KREngine/KREngine/Classes/KRMaterialManager.cpp index 623d9ab..5f38767 100644 --- a/KREngine/KREngine/Classes/KRMaterialManager.cpp +++ b/KREngine/KREngine/Classes/KRMaterialManager.cpp @@ -232,8 +232,9 @@ bool KRMaterialManager::load(const char *szName, KRDataBlock *data) { pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset); } else if(strcmp(szSymbol[0], "map_Reflection") == 0) { pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset); + } else if(strcmp(szSymbol[0], "map_ReflectionCube") == 0) { + pMaterial->setReflectionCube(szSymbol[1]); } - } } } diff --git a/KREngine/KREngine/Classes/KRTexture.cpp b/KREngine/KREngine/Classes/KRTexture.cpp index 45dfb01..cde014b 100644 --- a/KREngine/KREngine/Classes/KRTexture.cpp +++ b/KREngine/KREngine/Classes/KRTexture.cpp @@ -7,12 +7,50 @@ // #include "KRTexture.h" +#include "KRDataBlock.h" +#include -KRTexture::KRTexture(KRDataBlock *data, KRTextureManager *manager) { - m_pData = data; - m_pManager = manager; -} - -KRTexture::~KRTexture() { +KRTexture::KRTexture(KRContext &context) : KRContextObject(context) +{ + m_iHandle = 0; + m_textureMemUsed = 0; +} + +KRTexture::~KRTexture() +{ + long textureMemFreed = 0; + releaseHandle(textureMemFreed); +} + +void KRTexture::releaseHandle(long &textureMemUsed) { + if(m_iHandle != 0) { + textureMemUsed -= getMemSize(); + GLDEBUG(glDeleteTextures(1, &m_iHandle)); + m_iHandle = 0; + m_textureMemUsed = 0; + } +} + +long KRTexture::getMemSize() { + return m_textureMemUsed; // TODO - This is not 100% accurate, as loaded format may differ in size while in GPU memory +} + +GLuint KRTexture::getHandle(long &textureMemUsed, int max_dim, bool can_resize) { + // Constrain target LOD to be within mipmap levels of texture + int target_dim = max_dim; + if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; + if(target_dim > m_max_lod_max_dim) target_dim = m_max_lod_max_dim; + + if(can_resize && m_current_lod_max_dim != target_dim) { + releaseHandle(textureMemUsed); + } + if(m_iHandle == 0) { + if(createGLTexture(target_dim, m_textureMemUsed)) { + textureMemUsed += getMemSize(); + } else { + assert(false); + } + } + return m_iHandle; } diff --git a/KREngine/KREngine/Classes/KRTexture.h b/KREngine/KREngine/Classes/KRTexture.h index a2df119..fcbce35 100644 --- a/KREngine/KREngine/Classes/KRTexture.h +++ b/KREngine/KREngine/Classes/KRTexture.h @@ -35,25 +35,33 @@ #define KRTEXTURE_H #import "KREngine-common.h" +#import "KRContextObject.h" + -class KRTextureManager; class KRDataBlock; -class KRTexture { +class KRTexture : public KRContextObject{ public: - KRTexture(KRDataBlock *data, KRTextureManager *manager); + KRTexture(KRContext &context); virtual ~KRTexture(); - virtual GLuint getHandle(long &textureMemUsed, int max_dim, bool can_resize) = 0; + GLuint getHandle(long &textureMemUsed, int max_dim, bool can_resize); + void releaseHandle(long &textureMemUsed); + long getMemSize(); - virtual void releaseHandle(long &textureMemUsed) = 0; - virtual long getMemSize() = 0; protected: + virtual bool createGLTexture(int lod_max_dim, uint32_t &textureMemUsed) = 0; - KRDataBlock *m_pData; - KRTextureManager *m_pManager; + + GLuint m_iHandle; + uint32_t m_textureMemUsed; + + int m_current_lod_max_dim; + + uint32_t m_max_lod_max_dim; + uint32_t m_min_lod_max_dim; }; diff --git a/KREngine/KREngine/Classes/KRTexture2D.cpp b/KREngine/KREngine/Classes/KRTexture2D.cpp index ffeb6ce..17d4fc9 100644 --- a/KREngine/KREngine/Classes/KRTexture2D.cpp +++ b/KREngine/KREngine/Classes/KRTexture2D.cpp @@ -69,20 +69,27 @@ typedef struct _PVRTexHeader uint32_t numSurfs; } PVRTexHeader; -KRTexture2D::KRTexture2D(KRDataBlock *data, KRTextureManager *manager) : KRTexture(data, manager) { - m_iHandle = 0; +KRTexture2D::KRTexture2D(KRContext &context, KRDataBlock *data) : KRTexture(context) { + m_pData = data; m_current_lod_max_dim = 0; - m_textureMemUsed = 0; load(); } KRTexture2D::~KRTexture2D() { - long textureMemFreed = 0; - releaseHandle(textureMemFreed); delete m_pData; } +bool KRTexture2D::hasMipmaps() { + return m_blocks.size() > 1; +} +int KRTexture2D::getMaxMipMap() { + return m_max_lod_max_dim; +} + +int KRTexture2D::getMinMipMap() { + return m_min_lod_max_dim; +} bool KRTexture2D::load() { #if TARGET_OS_IPHONE @@ -164,8 +171,31 @@ bool KRTexture2D::load() { -bool KRTexture2D::createGLTexture(int lod_max_dim) { +bool KRTexture2D::createGLTexture(int lod_max_dim, uint32_t &textureMemUsed) { m_current_lod_max_dim = 0; + GLDEBUG(glGenTextures(1, &m_iHandle)); + if(m_iHandle == 0) { + return false; + } + GLDEBUG(glBindTexture(GL_TEXTURE_2D, m_iHandle)); + if (hasMipmaps()) { + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)); + } else { + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + } + if(!uploadTexture(GL_TEXTURE_2D, lod_max_dim, m_current_lod_max_dim, textureMemUsed)) { + GLDEBUG(glDeleteTextures(1, &m_iHandle)); + textureMemUsed = 0; + m_iHandle = 0; + m_current_lod_max_dim = 0; + return false; + } + + return true; +} + +bool KRTexture2D::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, uint32_t &textureMemUsed) +{ int width = m_iWidth; int height = m_iHeight; GLenum err; @@ -173,39 +203,25 @@ bool KRTexture2D::createGLTexture(int lod_max_dim) { if(m_blocks.size() == 0) { return false; } - - GLDEBUG(glGenTextures(1, &m_iHandle)); - if(m_iHandle == 0) { - return false; - } - GLDEBUG(glBindTexture(GL_TEXTURE_2D, m_iHandle)); - - if (m_blocks.size() > 1) { - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)); - } else { - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - } + int i=0; for(std::list::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { dataBlockStruct block = *itr; if(width <= lod_max_dim && height <= lod_max_dim) { - if(width > m_current_lod_max_dim) { - m_current_lod_max_dim = width; + if(width > current_lod_max_dim) { + current_lod_max_dim = width; } - if(height > m_current_lod_max_dim) { - m_current_lod_max_dim = height; + if(height > current_lod_max_dim) { + current_lod_max_dim = height; } - GLDEBUG(glCompressedTexImage2D(GL_TEXTURE_2D, i, m_internalFormat, width, height, 0, block.length, block.start)); + GLDEBUG(glCompressedTexImage2D(target, i, m_internalFormat, width, height, 0, block.length, block.start)); err = glGetError(); if (err != GL_NO_ERROR) { - GLDEBUG(glDeleteTextures(1, &m_iHandle)); - m_textureMemUsed = 0; - m_iHandle = 0; - lod_max_dim = 0; + return false; } - m_textureMemUsed += block.length; + textureMemUsed += block.length; i++; } @@ -220,38 +236,8 @@ bool KRTexture2D::createGLTexture(int lod_max_dim) { } return true; + } -GLuint KRTexture2D::getHandle(long &textureMemUsed, int max_dim, bool can_resize) { - // Constrain target LOD to be within mipmap levels of texture - int target_dim = max_dim; - if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; - if(target_dim > m_max_lod_max_dim) target_dim = m_max_lod_max_dim; - - if(can_resize && m_current_lod_max_dim != target_dim) { - releaseHandle(textureMemUsed); - } - if(m_iHandle == 0) { - if(createGLTexture(target_dim)) { - textureMemUsed += getMemSize(); - } else { - assert(false); - } - - //createGLTexture(); - } - return m_iHandle; -} -void KRTexture2D::releaseHandle(long &textureMemUsed) { - if(m_iHandle != 0) { - textureMemUsed -= getMemSize(); - GLDEBUG(glDeleteTextures(1, &m_iHandle)); - m_iHandle = 0; - m_textureMemUsed = 0; - } -} -long KRTexture2D::getMemSize() { - return m_textureMemUsed; // TODO - This is not 100% accurate, as loaded format may differ in size while in GPU memory -} diff --git a/KREngine/KREngine/Classes/KRTexture2D.h b/KREngine/KREngine/Classes/KRTexture2D.h index 2be974f..66ff421 100644 --- a/KREngine/KREngine/Classes/KRTexture2D.h +++ b/KREngine/KREngine/Classes/KRTexture2D.h @@ -43,23 +43,23 @@ using std::list; #include "KRTexture.h" -class KRTextureManager; - class KRTexture2D : public KRTexture { public: - KRTexture2D(KRDataBlock *data, KRTextureManager *manager); + KRTexture2D(KRContext &context, KRDataBlock *data); ~KRTexture2D(); + bool hasMipmaps(); + int getMaxMipMap(); + int getMinMipMap(); - virtual GLuint getHandle(long &textureMemUsed, int max_dim, bool can_resize); - virtual void releaseHandle(long &textureMemUsed); - virtual long getMemSize(); + bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, uint32_t &textureMemUsed); private: + KRDataBlock *m_pData; - bool createGLTexture(int lod_max_dim); + virtual bool createGLTexture(int lod_max_dim, uint32_t &textureMemUsed); + - GLuint m_iHandle; uint32_t m_iWidth; uint32_t m_iHeight; GLenum m_internalFormat; @@ -73,13 +73,7 @@ private: std::list m_blocks; bool load(); - - int m_current_lod_max_dim; - - uint32_t m_max_lod_max_dim; - uint32_t m_min_lod_max_dim; - - uint32_t m_textureMemUsed; + }; #endif diff --git a/KREngine/KREngine/Classes/KRTextureCube.cpp b/KREngine/KREngine/Classes/KRTextureCube.cpp index 68698c2..2a12b1e 100644 --- a/KREngine/KREngine/Classes/KRTextureCube.cpp +++ b/KREngine/KREngine/Classes/KRTextureCube.cpp @@ -30,28 +30,55 @@ // #include "KRTextureCube.h" +#include "KRTexture2D.h" +#include "KRContext.h" -KRTextureCube::KRTextureCube(KRDataBlock *data, KRTextureManager *manager) : KRTexture(data, manager) +KRTextureCube::KRTextureCube(KRContext &context, std::string name) : KRTexture(context) { - m_iHandle = 0; + m_name = name; + + m_max_lod_max_dim = 2048; + m_min_lod_max_dim = 64; + + for(int i=0; i<6; i++) { + std::string faceName = m_name + SUFFIXES[i]; + KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName.c_str()); + if(faceTexture) { + if(faceTexture->getMaxMipMap() < m_max_lod_max_dim) m_max_lod_max_dim = faceTexture->getMaxMipMap(); + if(faceTexture->getMinMipMap() > m_min_lod_max_dim) m_min_lod_max_dim = faceTexture->getMinMipMap(); + } + } } KRTextureCube::~KRTextureCube() { - if(m_iHandle != 0) glDeleteTextures(1, &m_iHandle); } -GLuint KRTextureCube::getHandle(long &textureMemUsed, int max_dim, bool can_resize) -{ - return 0; -} - -void KRTextureCube::releaseHandle(long &textureMemUsed) +bool KRTextureCube::createGLTexture(int lod_max_dim, uint32_t &textureMemUsed) { + m_current_lod_max_dim = 0; + GLDEBUG(glGenTextures(1, &m_iHandle)); + if(m_iHandle == 0) { + return false; + } -} + GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, m_iHandle)); + + bool bMipMaps = false; -long KRTextureCube::getMemSize() -{ - return 0; -} \ No newline at end of file + for(int i=0; i<6; i++) { + std::string faceName = m_name + SUFFIXES[i]; + KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName.c_str()); + if(faceTexture) { + if(faceTexture->hasMipmaps()) bMipMaps = true; + faceTexture->uploadTexture(TARGETS[i], lod_max_dim, m_current_lod_max_dim, textureMemUsed); + } + } + + if(bMipMaps) { + GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)); + } else { + GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + } + return true; +} diff --git a/KREngine/KREngine/Classes/KRTextureCube.h b/KREngine/KREngine/Classes/KRTextureCube.h index d771f59..a1441b6 100644 --- a/KREngine/KREngine/Classes/KRTextureCube.h +++ b/KREngine/KREngine/Classes/KRTextureCube.h @@ -33,26 +33,38 @@ #define KRTEXTURECUBE_H #include "KRTexture.h" -#include "KRTextureManager.h" class KRTextureCube : public KRTexture { public: - KRTextureCube(KRDataBlock *data, KRTextureManager *manager); + KRTextureCube(KRContext &context, std::string name); virtual ~KRTextureCube(); - virtual GLuint getHandle(long &textureMemUsed, int max_dim, bool can_resize); - virtual void releaseHandle(long &textureMemUsed); - virtual long getMemSize(); - private: - std::string m_frontTextureName; - std::string m_backTextureName; - std::string m_leftTextureName; - std::string m_rightTextureName; - std::string m_topTextureName; - std::string m_bottomTextureName; + virtual bool createGLTexture(int lod_max_dim, uint32_t &textureMemUsed); + + std::string m_name; GLuint m_iHandle; + + uint32_t m_textureMemUsed; + + const GLenum TARGETS[6] = { + 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 + }; + + const char *SUFFIXES[6] = { + "_positive_x", + "_negative_x", + "_positive_y", + "_negative_y", + "_positive_z", + "_negative_z" + }; }; diff --git a/KREngine/KREngine/Classes/KRTextureManager.cpp b/KREngine/KREngine/Classes/KRTextureManager.cpp index bc3aa18..0854eeb 100644 --- a/KREngine/KREngine/Classes/KRTextureManager.cpp +++ b/KREngine/KREngine/Classes/KRTextureManager.cpp @@ -51,7 +51,7 @@ KRTextureManager::~KRTextureManager() { } KRTexture *KRTextureManager::loadTexture(const char *szName, KRDataBlock *data) { - KRTexture *pTexture = new KRTexture2D(data, this); + KRTexture *pTexture = new KRTexture2D(getContext(), data); std::string lowerName = szName; std::transform(lowerName.begin(), lowerName.end(), @@ -63,17 +63,20 @@ KRTexture *KRTextureManager::loadTexture(const char *szName, KRDataBlock *data) return pTexture; } -KRTexture *KRTextureManager::loadTextureCube(const char *szName, KRDataBlock *data) { - KRTexture *pTexture = new KRTextureCube(data, this); - +KRTexture *KRTextureManager::getTextureCube(const char *szName) { std::string lowerName = szName; std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower); - - - m_textures[lowerName] = pTexture; - return pTexture; + map::iterator itr = m_textures.find(lowerName); + if(itr == m_textures.end()) { + KRTextureCube *pTexture = new KRTextureCube(getContext(), lowerName); + + m_textures[lowerName] = pTexture; + return pTexture; + } else { + return (*itr).second; + } } KRTexture *KRTextureManager::getTexture(const char *szName) { diff --git a/KREngine/KREngine/Classes/KRTextureManager.h b/KREngine/KREngine/Classes/KRTextureManager.h index 37107e8..c07ee96 100644 --- a/KREngine/KREngine/Classes/KRTextureManager.h +++ b/KREngine/KREngine/Classes/KRTextureManager.h @@ -61,8 +61,7 @@ public: void selectTexture(int iTextureUnit, KRTexture *pTexture, int lod_max_dim); KRTexture *loadTexture(const char *szName, KRDataBlock *data); - KRTexture *loadTextureCube(const char *szName, KRDataBlock *data); - + KRTexture *getTextureCube(const char *szName); KRTexture *getTexture(const char *szFile); long getMemUsed();