demotool/texture.cc

155 lines
3.3 KiB
C++

#include "externals.hh"
#include "utilities.hh"
#include "texture.hh"
T_Texture::T_Texture(
__rd__ const uint32_t width ,
__rd__ const uint32_t height ,
__rd__ const E_TexType type ,
__rd__ const uint32_t levels )
: levels_( levels ) , width_( width ) , height_( height )
{
assert( levels > 0 );
glGenTextures( 1 , &id_ );
glBindTexture( GL_TEXTURE_2D , id_ );
GLenum ifmt , fmt , dt;
switch ( type ) {
case E_TexType::RGBA8:
ifmt = GL_RGBA8;
fmt = GL_RGBA;
dt = GL_UNSIGNED_BYTE;
break;
case E_TexType::RGBA16F:
ifmt = GL_RGBA16F;
fmt = GL_RGBA;
dt = GL_FLOAT;
break;
case E_TexType::RGB8:
ifmt = GL_RGB8;
fmt = GL_RGB;
dt = GL_UNSIGNED_BYTE;
break;
case E_TexType::RGB16F:
ifmt = GL_RGB16F;
fmt = GL_RGB;
dt = GL_FLOAT;
break;
case E_TexType::R8:
ifmt = GL_R8;
fmt = GL_RED;
dt = GL_UNSIGNED_BYTE;
break;
case E_TexType::R16F:
ifmt = GL_R16F;
fmt = GL_RED;
dt = GL_FLOAT;
break;
}
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_BASE_LEVEL , 0 );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL , levels - 1 );
glTexParameterf( GL_TEXTURE_2D , GL_TEXTURE_MIN_LOD , 0 );
glTexParameterf( GL_TEXTURE_2D , GL_TEXTURE_MAX_LOD , levels - 1 );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST );
uint32_t w = width , h = height;
for ( auto i = 0u ; i < levels ; i ++ ) {
#ifdef INTRUSIVE_TRACES
printf( "init %p txid %d lv %d sz %dx%d\n" , this , id_ ,
i , w , h );
#endif
glTexImage2D( GL_TEXTURE_2D , i , ifmt , w , h , 0 , fmt , dt , nullptr );
w >>= 1;
h >>= 1;
assert( w && h );
}
GL_CHECK( );
}
T_Texture::~T_Texture( )
{
glDeleteTextures( 1 , &id_ );
}
T_Texture& T_Texture::samplingMode(
__rd__ const E_TexSampling mode )
{
glBindTexture( GL_TEXTURE_2D , id_ );
GLenum min , max;
switch ( mode ) {
case E_TexSampling::NEAREST:
min = levels_ > 1 ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
max = GL_NEAREST;
break;
case E_TexSampling::LINEAR:
min = levels_ > 1 ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
max = GL_LINEAR;
break;
}
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , min );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , max );
return *this;
}
T_Texture& T_Texture::wrap(
__rd__ const E_TexWrap mode )
{
GLenum gm;
switch ( mode ) {
case E_TexWrap::REPEAT:
gm = GL_REPEAT;
break;
case E_TexWrap::CLAMP_EDGE:
gm = GL_CLAMP_TO_EDGE;
break;
case E_TexWrap::CLAMP_BORDER:
gm = GL_CLAMP_TO_BORDER;
break;
}
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , gm );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , gm );
return *this;
}
/*============================================================================*/
T_TextureBinding::T_TextureBinding(
__rd__ const uint32_t binding )
: binding_( binding ) , uniform_( 0 ) , texture_( nullptr )
{ }
void T_TextureBinding::clear( )
{
uniform_ = 0;
texture_ = nullptr;
}
void T_TextureBinding::set(
__rd__ const uint32_t uniform ,
__rd__ T_Texture const& texture )
{
uniform_ = uniform;
texture_ = &texture;
}
void T_TextureBinding::bind( ) const
{
glBindTextureUnit( binding_ ,
texture_ ? texture_->id( ) : 0 );
glUniform1i( uniform_ , binding_ );
assert( glGetError( ) == GL_NO_ERROR );
}