2#include <Core/Tasks/Task.hpp>
3#include <Core/Tasks/TaskQueue.hpp>
4#include <Core/Utils/Log.hpp>
5#include <Engine/Data/Texture.hpp>
6#include <Engine/RadiumEngine.hpp>
8#include <glbinding/gl/enum.h>
9#include <globjects/Texture.h>
16using namespace Core::Utils;
19 m_textureParameters { texParameters }, m_texture { nullptr }, m_isMipMapped { false } {}
25 m_texture(
std::move( texture ) ) {}
28 std::string getName()
const override {
return "DeleteTextureTask"; };
31 virtual void process()
override {
41 if ( m_updateImageTaskId.isValid() ) {
42 RadiumEngine::getInstance()->removeGpuTask( m_updateImageTaskId );
45 if ( m_updateSamplerTaskId.isValid() ) {
46 RadiumEngine::getInstance()->removeGpuTask( m_updateSamplerTaskId );
54 if ( !isSupportedTarget() )
return;
57 computeIsMipMappedFlag();
67 if ( !isSupportedTarget() )
return;
68 computeIsMipMappedFlag();
78 if (
auto engine = RadiumEngine::getInstance() ) {
79 auto task = std::make_unique<DeleteTextureTask>(
std::move( m_texture ) );
95 m_textureParameters.image.texels = newData;
100 m_textureParameters.image.width = w;
101 m_textureParameters.image.height = h;
102 m_textureParameters.image.depth = d;
103 m_textureParameters.image.texels = pix;
104 if ( createTexture() ) {
105 computeIsMipMappedFlag();
119 m_textureParameters.image = imageParameters;
125 m_textureParameters.sampler = samplerParameters;
130 if ( unit >= 0 ) { m_texture->bindActive( uint( unit ) ); }
131 else { m_texture->bind(); }
139 m_texture->bindImageTexture(
140 uint( unit ), level, layered, layer, access, m_textureParameters.image.
internalFormat );
148 bool hasAlpha =
false;
149 switch ( image.format ) {
162 LOG( logERROR ) <<
"Textures with format " << image.format <<
" can't be linearized.\n";
165 if ( image.type == GL_TEXTURE_CUBE_MAP ) { linearizeCubeMap( image, numComp, hasAlpha ); }
167 srgbToLinearRgb(
reinterpret_cast<uint8_t*
>( std::get<0>( image.texels ).get() ),
178bool Texture::isSupportedTarget() {
179 if ( ( m_textureParameters.image.target != GL_TEXTURE_1D ) &&
180 ( m_textureParameters.image.target != GL_TEXTURE_2D ) &&
181 ( m_textureParameters.image.target != GL_TEXTURE_RECTANGLE ) &&
182 ( m_textureParameters.image.target != GL_TEXTURE_3D ) &&
183 ( m_textureParameters.image.target != GL_TEXTURE_CUBE_MAP ) ) {
184 LOG( logERROR ) <<
"Texture of type " << m_textureParameters.image.target
185 <<
" must be generated explicitly!";
191void Texture::computeIsMipMappedFlag() {
192 m_isMipMapped = !( m_textureParameters.sampler.
minFilter == GL_NEAREST ||
193 m_textureParameters.sampler.
minFilter == GL_LINEAR );
196bool Texture::createTexture() {
197 if ( m_texture ==
nullptr ) {
198 m_texture = globjects::Texture::create( m_textureParameters.image.target );
207 if ( m_updateImageTaskId.isInvalid() ) {
208 auto taskFunc = [
this]() {
211 this->createTexture();
213 m_updateImageTaskId = Core::TaskQueue::TaskId::Invalid();
215 auto task = std::make_unique<Core::FunctionTask>( taskFunc,
getName() );
216 m_updateImageTaskId = RadiumEngine::getInstance()->addGpuTask(
std::move( task ) );
221 if ( m_updateSamplerTaskId.isInvalid() ) {
222 auto taskFunc = [
this]() {
225 this->createTexture();
227 m_updateSamplerTaskId = Core::TaskQueue::TaskId::Invalid();
229 auto task = std::make_unique<Core::FunctionTask>( taskFunc,
getName() );
230 m_updateSamplerTaskId = RadiumEngine::getInstance()->addGpuTask(
std::move( task ) );
235 CORE_ASSERT( m_texture !=
nullptr,
"Cannot update non initialized texture" );
236 switch ( m_texture->target() ) {
237 case GL_TEXTURE_1D: {
238 m_texture->image1D( 0,
240 GLsizei( m_textureParameters.image.width ),
242 m_textureParameters.image.format,
243 m_textureParameters.image.type,
248 case GL_TEXTURE_RECTANGLE: {
249 m_texture->image2D( 0,
251 GLsizei( m_textureParameters.image.width ),
252 GLsizei( m_textureParameters.image.height ),
254 m_textureParameters.image.format,
255 m_textureParameters.image.type,
259 case GL_TEXTURE_3D: {
260 m_texture->image3D( 0,
262 GLsizei( m_textureParameters.image.width ),
263 GLsizei( m_textureParameters.image.height ),
264 GLsizei( m_textureParameters.image.depth ),
266 m_textureParameters.image.format,
267 m_textureParameters.image.type,
271 case GL_TEXTURE_CUBE_MAP: {
273 auto cubeMap = m_textureParameters.image.
getCubeMap();
281 m_texture->cubeMapImage( 0,
283 GLsizei( m_textureParameters.image.width ),
284 GLsizei( m_textureParameters.image.height ),
286 m_textureParameters.image.format,
287 m_textureParameters.image.type,
293 CORE_ASSERT( 0,
"Unsupported texture type ?" );
297 if ( m_isMipMapped ) { m_texture->generateMipmap(); }
302void Texture::readFromGpu(
int level ) {
303 CORE_ASSERT( m_texture !=
nullptr,
"Cannot get non initialized texture" );
305 "Can only get image typf" );
306 CORE_ASSERT( m_textureParameters.image.
getTexels() !=
nullptr,
"Can only get image type" );
307 CORE_ASSERT( GL_TEXTURE_CUBE_MAP != m_texture->target(),
"Cannot get cube map" );
309 m_texture->getImage( level,
310 m_textureParameters.image.format,
311 m_textureParameters.image.type,
312 m_textureParameters.image.getImage().
get() );
317 switch ( m_texture->target() ) {
318 case GL_TEXTURE_CUBE_MAP:
320 m_texture->setParameter( GL_TEXTURE_WRAP_R, m_textureParameters.sampler.
wrapR );
324 case GL_TEXTURE_RECTANGLE:
325 m_texture->setParameter( GL_TEXTURE_WRAP_T, m_textureParameters.sampler.
wrapT );
329 m_texture->setParameter( GL_TEXTURE_WRAP_S, m_textureParameters.sampler.
wrapS );
335 m_texture->setParameter( GL_TEXTURE_MIN_FILTER, m_textureParameters.sampler.
minFilter );
337 m_texture->setParameter( GL_TEXTURE_MAG_FILTER, m_textureParameters.sampler.
magFilter );
342void Texture::srgbToLinearRgb( uint8_t* texels,
347 bool hasAlphaChannel ) {
349 auto linearize = []( uint8_t in ) -> uint8_t {
351 float c = float( in ) / 255;
352 if ( c < 0.04045 ) { c = c / 12.92f; }
353 else { c =
std::pow( ( ( c + 0.055f ) / ( 1.055f ) ), 2.4f ); }
354 return uint8_t( c * 255 );
356 uint numValues = hasAlphaChannel ? numComponent - 1 : numComponent;
357#pragma omp parallel for
358 for (
int i = 0; i < int( width * height * depth ); ++i ) {
360 for ( uint p = i * numComponent; p < i * numComponent + numValues; ++p ) {
366void Texture::linearizeCubeMap( ImageParameters& image, uint numComponent,
bool hasAlphaChannel ) {
367 if ( image.type == gl::GLenum::GL_UNSIGNED_BYTE ) {
370 const auto cubeMap = image.getCubeMap();
371 for (
int i = 0; i < 6; ++i ) {
372 srgbToLinearRgb(
reinterpret_cast<uint8_t*
>( cubeMap[i].get() ),
void bind(int unit=-1)
Bind the texture to GPU texture unit to enable its use in a shader. Need active OpenGL context.
void registerUpdateImageDataTask()
Regiter gpu task to RadiumEngine. Will call sendImageDataToGpu during next RadiumEngine::runGpuTasks(...
void setSamplerParameters(const SamplerParameters &samplerParameters)
set TerctureParameters.samples
void initialize()
Generate the OpenGL representation of the texture according to the stored TextureData (delayed).
void destroyNow()
Generate the GPU representation of the texture right now. Need an active OpenGL context.
void destroy()
destroy the GPU texture representation.
void setImageParameters(const ImageParameters &imageParameters)
set TextureParameters.image
void updateData(std::shared_ptr< void > newData)
Update the cpu representation of data contained by the texture.
~Texture()
Texture destructor. Both internal data and GPU representation are deleted.
void sendImageDataToGpu()
Send image data to the GPU and generate mipmap if needed.
void resize(size_t w=1, size_t h=1, size_t d=1, std::shared_ptr< void > pix=nullptr)
Resize the texture. Need active OpenGL context.
void setParameters(const TextureParameters &textureParameters)
set TextureParameters.
std::string getName() const
void initializeNow()
Generate the GPU representation of the texture right now. Need an active OpenGL context.
static void linearize(ImageParameters &image)
Convert a color texture from sRGB to Linear RGB spaces.
void bindImageTexture(int unit, GLint level, GLboolean layered, GLint layer, GLenum access)
Bind the texture to an image unit for the purpose of reading and writing it from shaders....
void registerUpdateSamplerParametersTask()
Regiter gpu task to RadiumEngine. Will call sendSamplerParametersToGpu during next RadiumEngine::runG...
Texture(const Texture &)=delete
Textures are not copyable, delete copy constructor.
void sendSamplerParametersToGpu()
Send sampler parameters to the GPU.
hepler function to manage enum as underlying types in VariableSet
bool isLinear
set to true when linearize texture rgb component. If true, linearize has no effect.
const CubeMapType getCubeMap() const
GLenum internalFormat
OpenGL internal format (WARNING, for Integer textures, must be GL_XXX_INTEGER)
const void * getTexels() const
bool isTexelOfType() const
check which type is held by texels
GPU Sampler configuration.
GLenum wrapT
OpenGL wrap mode in the t direction.
GLenum minFilter
OpenGL minification filter ( GL_LINEAR or GL_NEAREST or GL_XXX_MIPMAP_YYY )
GLenum wrapS
OpenGL wrap mode in the s direction.
GLenum wrapR
OpenGL wrap mode in the r direction.
GLenum magFilter
OpenGL magnification filter ( GL_LINEAR or GL_NEAREST )
Describes the sampler and image of a texture.