#include "externals.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 ++ ) { glTexImage2D( GL_TEXTURE_2D , i , ifmt , w , h , 0 , fmt , dt , nullptr ); w >>= 1; h >>= 1; assert( w && h ); } assert( glGetError( ) == GL_NO_ERROR ); } 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 ); }