SparrowRenderer/src/texture.cpp

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;
}