kick
/Users/morten/Programmering/cpp/kick/src/kick/texture/texture2d.cpp
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 }
 All Classes Functions Variables