kick
|
00001 // 00002 // texture.cpp 00003 // KickCPP 00004 // 00005 // Created by morten on 16/03/14. 00006 // Copyright (c) 2014 Morten Nobel-Joergensen. All rights reserved. 00007 // 00008 00009 #include "texture2d.h" 00010 00011 #include "kick/core/debug.h" 00012 #ifndef EMSCRIPTEN 00013 #ifdef _WIN32 00014 #include <SDL_surface.h> 00015 #else 00016 #include <SDL2/SDL_surface.h> 00017 #endif 00018 #endif 00019 using namespace std; 00020 00021 namespace kick { 00022 Texture2D::Texture2D(TextureSampler textureSampler) 00023 { 00024 glGenTextures(1, &mTextureid); 00025 setTextureSampler(textureSampler); 00026 } 00027 00028 Texture2D::Texture2D(Texture2D&& m) 00029 : mTextureid(m.mTextureid) 00030 { 00031 m.mTextureid = 0; 00032 } 00033 00034 Texture2D::~Texture2D(){ 00035 glDeleteTextures(1, &mTextureid); 00036 } 00037 00038 void Texture2D::bind(int textureSlot){ 00039 glActiveTexture(GL_TEXTURE0 + textureSlot); 00040 glBindTexture(GL_TEXTURE_2D, mTextureid); 00041 } 00042 00043 void Texture2D::setData(const Texture2DData& data, const ImageFormat& imageFormat){ 00044 setData(data.width(), data.height(),data.data(), imageFormat); 00045 } 00046 00047 void Texture2D::setData(int width, int height, const char* data, const ImageFormat& imageFormat){ 00048 this->mWidth = width; 00049 this->mHeight = height; 00050 this->mImageFormat = imageFormat; 00051 GLenum target = GL_TEXTURE_2D; 00052 GLint border = 0; // must be 0 00053 00054 glBindTexture(GL_TEXTURE_2D, mTextureid); 00055 00056 glTexImage2D(target, imageFormat.mipmapLevel, imageFormat.internalFormat, width, height, border, imageFormat.format, imageFormat.type, data); 00057 if (imageFormat.mipmap != Mipmap::None){ 00058 glGenerateMipmap(GL_TEXTURE_2D); 00059 } 00060 } 00061 00062 void Texture2D::setTextureSampler(const TextureSampler & textureSampler){ 00063 this->mTextureSampler = textureSampler; 00064 glBindTexture(GL_TEXTURE_2D, mTextureid); 00065 00066 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast<GLint>(textureSampler.wrapS)); 00067 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, static_cast<GLint>(textureSampler.wrapT)); 00068 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, static_cast<GLint>(textureSampler.filterMag)); 00069 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, static_cast<GLint>(textureSampler.filterMin)); 00070 } 00071 00072 TextureSampler Texture2D::textureSampler() const{ 00073 return mTextureSampler; 00074 } 00075 00076 ImageFormat Texture2D::imageFormat() const { 00077 return mImageFormat; 00078 } 00079 00080 void Texture2D::saveBMPImage(string filename) { 00081 vector<char> res(mWidth * mHeight *4); 00082 #if defined(KICK_CONTEXT_ES2) 00083 logWarning("Texture2D::getPngImage() is unsupported on ES2"); 00084 #elif defined(EMSCRIPTEN) 00085 logWarning("Texture2D::getPngImage() is unsupported on EMSCRIPTEN"); 00086 #else 00087 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, res.data()); 00088 #endif 00089 00090 #ifndef EMSCRIPTEN 00091 SDL_Surface* sdlSurface = SDL_CreateRGBSurfaceFrom(res.data(), mWidth, mHeight,32, mWidth *4, 0xff,0xff<<8,0xff<<16,0xff<<24); 00092 00093 SDL_SaveBMP(sdlSurface, filename.c_str()); 00094 sdlSurface->pixels = nullptr; 00095 SDL_FreeSurface(sdlSurface); 00096 #endif 00097 } 00098 00099 00100 void Texture2D::setEmptyColorTexture(int width, int height, int colorChannels, bool fpTexture) { 00101 ImageFormat imageFormat; 00102 if (fpTexture){ 00103 if (colorChannels == 4){ 00104 imageFormat.internalFormat = GL_RGBA32F; 00105 } else if (colorChannels == 3){ 00106 imageFormat.internalFormat = GL_RGB32F; 00107 } else if (colorChannels == 2){ 00108 imageFormat.internalFormat = GL_RG32F; 00109 } else if (colorChannels == 1){ 00110 imageFormat.internalFormat = GL_R32F; 00111 } 00112 } else { 00113 if (colorChannels == 4){ 00114 imageFormat.internalFormat = GL_RGBA8; 00115 } else if (colorChannels == 3){ 00116 imageFormat.internalFormat = GL_RGB8; 00117 } else if (colorChannels == 2){ 00118 imageFormat.internalFormat = GL_RG8; 00119 } else if (colorChannels == 1){ 00120 imageFormat.internalFormat = GL_R8; 00121 } 00122 } 00123 if (colorChannels == 4){ 00124 imageFormat.format = GL_RGBA; 00125 } else if (colorChannels == 3){ 00126 imageFormat.format = GL_RGB; 00127 } else if (colorChannels == 2){ 00128 imageFormat.format = GL_RG; 00129 } else if (colorChannels == 1){ 00130 imageFormat.format = GL_RED; 00131 } 00132 setData(width, height, nullptr, imageFormat); 00133 } 00134 00135 void Texture2D::setEmptyDepthTexture(int width, int height, int bits, bool fpTexture) { 00136 ImageFormat imageFormat; 00137 if (bits == 16){ 00138 if (fpTexture){ 00139 logWarning("Unsupported fpTexture for 16 bit depth texture"); 00140 } 00141 imageFormat.internalFormat = GL_DEPTH_COMPONENT16; 00142 } else if (bits == 24){ 00143 if (fpTexture){ 00144 logWarning("Unsupported fpTexture for 24 bit depth texture"); 00145 } 00146 imageFormat.internalFormat = GL_DEPTH_COMPONENT24; 00147 } else if (bits == 32 && fpTexture) { 00148 imageFormat.internalFormat = GL_DEPTH_COMPONENT32F; 00149 } else { 00150 if (bits != 32){ 00151 logWarning("Unsupported bit depth for depth texture"); 00152 } 00153 imageFormat.internalFormat = GL_DEPTH_COMPONENT32; 00154 } 00155 00156 imageFormat.format = GL_DEPTH_COMPONENT; 00157 00158 setData(width, height, nullptr, imageFormat); 00159 } 00160 00161 Texture2DData Texture2D::data() { 00162 bind(0); 00163 vector<char> res(dataSize()); 00164 GLenum type = GL_UNSIGNED_BYTE; 00165 switch (mImageFormat.internalFormat){ 00166 case GL_RGBA32F: 00167 case GL_RGB32F: 00168 case GL_RG32F: 00169 case GL_R32F: 00170 case GL_DEPTH_COMPONENT32F: 00171 type = GL_FLOAT; 00172 } 00173 glGetTexImage(GL_TEXTURE_2D, 0, mImageFormat.format, type, res.data()); 00174 return Texture2DData(res, mWidth, mHeight); 00175 } 00176 00177 int Texture2D::dataSize(){ 00178 int bytesPerTexel = 4; 00179 switch (mImageFormat.internalFormat){ 00180 case GL_RGBA32F: 00181 bytesPerTexel = 16; 00182 break; 00183 case GL_RGB32F: 00184 bytesPerTexel = 12; 00185 break; 00186 case GL_RG32F: 00187 bytesPerTexel = 8; 00188 break; 00189 case GL_DEPTH_COMPONENT32: 00190 case GL_DEPTH_COMPONENT32F: 00191 case GL_RGBA8: 00192 case GL_R32F: 00193 bytesPerTexel = 4; 00194 break; 00195 case GL_DEPTH_COMPONENT24: 00196 case GL_RGB8: 00197 bytesPerTexel = 3; 00198 break; 00199 case GL_DEPTH_COMPONENT16: 00200 case GL_RG8: 00201 bytesPerTexel = 2; 00202 break; 00203 case GL_R8: 00204 bytesPerTexel = 1; 00205 break; 00206 default: 00207 logWarning("Unknown size"); 00208 } 00209 return mWidth * mHeight * bytesPerTexel; 00210 } 00211 }