197 lines
5.0 KiB
C++
197 lines
5.0 KiB
C++
#include "texture.h"
|
|
|
|
#include "image.h"
|
|
|
|
Texture::Texture(GLenum format,
|
|
GLenum internal_format,
|
|
int width,
|
|
int height,
|
|
GLenum dataType,
|
|
GLenum texTarget) :
|
|
m_texUnit(0),
|
|
m_target(texTarget),
|
|
m_format(format),
|
|
m_internal_format(internal_format),
|
|
m_width(width),
|
|
m_height(height),
|
|
m_dataType(dataType),
|
|
m_hasMipMaps(false)
|
|
{
|
|
glGenTextures(1, &m_texId);
|
|
glBindTexture(m_target, m_texId);
|
|
switch(m_target)
|
|
{
|
|
case GL_TEXTURE_2D :
|
|
glTexImage2D(m_target, 0, internal_format, width, height, 0, format, dataType, NULL);
|
|
setWrap(GL_REPEAT);
|
|
setFiltering(GL_LINEAR);
|
|
break;
|
|
case GL_TEXTURE_RECTANGLE :
|
|
glTexImage2D(m_target, 0, internal_format, width, height, 0, format, dataType, NULL);
|
|
setWrap(GL_CLAMP_TO_EDGE);
|
|
setFiltering(GL_LINEAR);
|
|
break;
|
|
case GL_TEXTURE_CUBE_MAP :
|
|
for(int i=0; i<6; ++i)
|
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internal_format, width, height, 0, format, dataType, NULL);
|
|
setWrap(GL_CLAMP_TO_EDGE);
|
|
setFiltering(GL_LINEAR);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
Texture::Texture(Image* myImage, bool makeMipMaps) :
|
|
m_texUnit(0),
|
|
m_target(GL_TEXTURE_2D),
|
|
m_width(myImage->width),
|
|
m_height(myImage->height),
|
|
m_dataType(GL_UNSIGNED_BYTE),
|
|
m_hasMipMaps(makeMipMaps)
|
|
{
|
|
glGenTextures(1, &m_texId);
|
|
glBindTexture(m_target, m_texId);
|
|
initPixels(myImage, GL_TEXTURE_2D);
|
|
setWrap(GL_REPEAT);
|
|
setFiltering(GL_LINEAR);
|
|
if(makeMipMaps)
|
|
createMipMaps();
|
|
}
|
|
|
|
Texture::Texture(Image* myCubemapImages[6], bool makeMipMaps) :
|
|
m_texUnit(0),
|
|
m_target(GL_TEXTURE_CUBE_MAP),
|
|
m_width(myCubemapImages[0]->width),
|
|
m_height(myCubemapImages[0]->height),
|
|
m_dataType(GL_UNSIGNED_BYTE),
|
|
m_hasMipMaps(makeMipMaps)
|
|
{
|
|
glGenTextures(1, &m_texId);
|
|
glBindTexture(m_target, m_texId);
|
|
for(int i=0; i<6; ++i)
|
|
initPixels(myCubemapImages[i], GL_TEXTURE_CUBE_MAP_POSITIVE_X + i);
|
|
setWrap(GL_CLAMP_TO_EDGE);
|
|
setFiltering(GL_LINEAR);
|
|
if(makeMipMaps)
|
|
createMipMaps();
|
|
}
|
|
|
|
Texture::Texture(Texture* tex, bool halfDim) :
|
|
m_texUnit(0),
|
|
m_target(tex->m_target),
|
|
m_format(tex->m_format),
|
|
m_internal_format(tex->m_internal_format),
|
|
m_width(tex->m_width),
|
|
m_height(tex->m_height),
|
|
m_dataType(tex->m_dataType),
|
|
m_hasMipMaps(false)
|
|
{
|
|
glGenTextures(1, &m_texId);
|
|
glBindTexture(m_target, m_texId);
|
|
if(halfDim)
|
|
{
|
|
m_width /= 2;
|
|
m_height /= 2;
|
|
}
|
|
glTexImage2D(m_target, 0, m_internal_format, m_width, m_height, 0, m_format, m_dataType, NULL);
|
|
}
|
|
|
|
Texture::~Texture()
|
|
{
|
|
glDeleteTextures(1, &m_texId);
|
|
}
|
|
|
|
void Texture::initPixels(Image* myImage, GLenum target)
|
|
{
|
|
switch(myImage->depth)
|
|
{
|
|
case 32:
|
|
m_format = GL_RGBA;
|
|
m_internal_format = GL_RGBA;
|
|
break;
|
|
case 24:
|
|
m_format = GL_RGB;
|
|
m_internal_format = GL_RGB;
|
|
break;
|
|
case 8:
|
|
m_format = GL_RED;
|
|
m_internal_format = GL_R8;
|
|
break;
|
|
}
|
|
glTexImage2D(target, 0, m_internal_format, m_width, m_height, 0, m_format, m_dataType, myImage->pixels.data());
|
|
}
|
|
|
|
void Texture::setWrap(GLint wrap)
|
|
{
|
|
setParameter(GL_TEXTURE_WRAP_S, wrap);
|
|
setParameter(GL_TEXTURE_WRAP_T, wrap);
|
|
setParameter(GL_TEXTURE_WRAP_R, wrap);
|
|
}
|
|
|
|
void Texture::setFiltering(GLint filter)
|
|
{
|
|
setParameter(GL_TEXTURE_MIN_FILTER, filter);
|
|
setParameter(GL_TEXTURE_MAG_FILTER, filter);
|
|
}
|
|
|
|
void Texture::setParameter(GLenum parameter, GLenum value)
|
|
{
|
|
glBindTexture(m_target, m_texId);
|
|
glTexParameteri(m_target, parameter, value);
|
|
}
|
|
|
|
void Texture::createMipMaps()
|
|
{
|
|
m_hasMipMaps = true;
|
|
glGenerateMipmap(m_target);
|
|
setParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
}
|
|
|
|
void Texture::bind(int unit)
|
|
{
|
|
if(unit >= 0)
|
|
m_texUnit = unit;
|
|
glActiveTexture(GL_TEXTURE0+m_texUnit);
|
|
glBindTexture(m_target, m_texId);
|
|
}
|
|
|
|
void Texture::unbind()
|
|
{
|
|
glActiveTexture(GL_TEXTURE0+m_texUnit);
|
|
glBindTexture(m_target, 0);
|
|
}
|
|
|
|
Image* Texture::getData(int faceId)
|
|
{
|
|
bind();
|
|
int nbVal;
|
|
int nbImages;
|
|
switch(m_format)
|
|
{
|
|
case GL_RGBA: nbVal = 4; break;
|
|
case GL_RGB: nbVal = 3; break;
|
|
case GL_RED: nbVal = 1; break;
|
|
case GL_DEPTH_COMPONENT: nbVal = 1; break;
|
|
default: return NULL;
|
|
}
|
|
switch(m_target)
|
|
{
|
|
case GL_TEXTURE_2D_ARRAY: nbImages = 3; break; // TODO : add a member specifying how many layers has the texture
|
|
default: nbImages = 1; break;
|
|
}
|
|
|
|
int size = nbVal*m_width*m_height*nbImages;
|
|
|
|
Image *img = new Image();
|
|
img->depth = nbVal*8;
|
|
img->height = m_height;
|
|
img->width = m_width;
|
|
img->allocate(size);
|
|
if(m_target == GL_TEXTURE_CUBE_MAP)
|
|
glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X+faceId, 0, m_format, GL_UNSIGNED_BYTE, img->pixels.data());
|
|
else
|
|
glGetTexImage(m_target, 0, m_format, GL_UNSIGNED_BYTE, img->pixels.data());
|
|
return img;
|
|
}
|