2#include <Core/Tasks/Task.hpp>
3#include <Core/Tasks/TaskQueue.hpp>
4#include <Core/Utils/Index.hpp>
5#include <Core/Utils/Log.hpp>
6#include <Engine/Data/Texture.hpp>
7#include <Engine/OpenGL.hpp>
8#include <Engine/RadiumEngine.hpp>
11#include <glbinding-aux/types_to_string.h>
12#include <glbinding/gl/enum.h>
13#include <globjects/Texture.h>
14#include <globjects/base/Instantiator.inl>
22using namespace Core::Utils;
25 m_textureParameters { texParameters }, m_texture { nullptr }, m_isMipMapped { false } {}
31 m_texture(
std::move( texture ) ) {}
34 std::string getName()
const override {
return "DeleteTextureTask"; };
37 virtual void process()
override {
47 if ( m_updateImageTaskId.isValid() ) {
48 RadiumEngine::getInstance()->removeGpuTask( m_updateImageTaskId );
51 if ( m_updateSamplerTaskId.isValid() ) {
52 RadiumEngine::getInstance()->removeGpuTask( m_updateSamplerTaskId );
60 if ( !isSupportedTarget() )
return;
63 computeIsMipMappedFlag();
73 if ( !isSupportedTarget() )
return;
74 computeIsMipMappedFlag();
84 if (
auto engine = RadiumEngine::getInstance() ) {
85 auto task = std::make_unique<DeleteTextureTask>(
std::move( m_texture ) );
101 m_textureParameters.image.texels = newData;
106 m_textureParameters.image.width = w;
107 m_textureParameters.image.height = h;
108 m_textureParameters.image.depth = d;
109 m_textureParameters.image.texels = pix;
110 if ( createTexture() ) {
111 computeIsMipMappedFlag();
125 m_textureParameters.image = imageParameters;
131 m_textureParameters.sampler = samplerParameters;
136 if ( unit >= 0 ) { m_texture->bindActive( uint( unit ) ); }
137 else { m_texture->bind(); }
145 m_texture->bindImageTexture(
146 uint( unit ), level, layered, layer, access, m_textureParameters.image.
internalFormat );
154 bool hasAlpha =
false;
155 switch ( image.format ) {
168 LOG( logERROR ) <<
"Textures with format " << image.format <<
" can't be linearized.\n";
171 if ( image.type == GL_TEXTURE_CUBE_MAP ) { linearizeCubeMap( image, numComp, hasAlpha ); }
173 srgbToLinearRgb(
reinterpret_cast<uint8_t*
>( std::get<0>( image.texels ).get() ),
184bool Texture::isSupportedTarget() {
185 if ( ( m_textureParameters.image.target != GL_TEXTURE_1D ) &&
186 ( m_textureParameters.image.target != GL_TEXTURE_2D ) &&
187 ( m_textureParameters.image.target != GL_TEXTURE_RECTANGLE ) &&
188 ( m_textureParameters.image.target != GL_TEXTURE_3D ) &&
189 ( m_textureParameters.image.target != GL_TEXTURE_CUBE_MAP ) ) {
190 LOG( logERROR ) <<
"Texture of type " << m_textureParameters.image.target
191 <<
" must be generated explicitly!";
197void Texture::computeIsMipMappedFlag() {
198 m_isMipMapped = !( m_textureParameters.sampler.
minFilter == GL_NEAREST ||
199 m_textureParameters.sampler.
minFilter == GL_LINEAR );
202bool Texture::createTexture() {
203 if ( m_texture ==
nullptr ) {
204 m_texture = globjects::Texture::create( m_textureParameters.image.target );
213 if ( m_updateImageTaskId.isInvalid() ) {
214 auto taskFunc = [
this]() {
217 this->createTexture();
219 m_updateImageTaskId = Core::TaskQueue::TaskId::Invalid();
221 auto task = std::make_unique<Core::FunctionTask>( taskFunc,
getName() );
222 m_updateImageTaskId = RadiumEngine::getInstance()->addGpuTask(
std::move( task ) );
227 if ( m_updateSamplerTaskId.isInvalid() ) {
228 auto taskFunc = [
this]() {
231 this->createTexture();
233 m_updateSamplerTaskId = Core::TaskQueue::TaskId::Invalid();
235 auto task = std::make_unique<Core::FunctionTask>( taskFunc,
getName() );
236 m_updateSamplerTaskId = RadiumEngine::getInstance()->addGpuTask(
std::move( task ) );
241 CORE_ASSERT( m_texture !=
nullptr,
"Cannot update non initialized texture" );
242 switch ( m_texture->target() ) {
243 case GL_TEXTURE_1D: {
244 m_texture->image1D( 0,
246 GLsizei( m_textureParameters.image.width ),
248 m_textureParameters.image.format,
249 m_textureParameters.image.type,
254 case GL_TEXTURE_RECTANGLE: {
255 m_texture->image2D( 0,
257 GLsizei( m_textureParameters.image.width ),
258 GLsizei( m_textureParameters.image.height ),
260 m_textureParameters.image.format,
261 m_textureParameters.image.type,
265 case GL_TEXTURE_3D: {
266 m_texture->image3D( 0,
268 GLsizei( m_textureParameters.image.width ),
269 GLsizei( m_textureParameters.image.height ),
270 GLsizei( m_textureParameters.image.depth ),
272 m_textureParameters.image.format,
273 m_textureParameters.image.type,
277 case GL_TEXTURE_CUBE_MAP: {
279 auto cubeMap = m_textureParameters.image.
getCubeMap();
287 m_texture->cubeMapImage( 0,
289 GLsizei( m_textureParameters.image.width ),
290 GLsizei( m_textureParameters.image.height ),
292 m_textureParameters.image.format,
293 m_textureParameters.image.type,
299 CORE_ASSERT( 0,
"Unsupported texture type ?" );
303 if ( m_isMipMapped ) { m_texture->generateMipmap(); }
308void Texture::readFromGpu(
int level ) {
309 CORE_ASSERT( m_texture !=
nullptr,
"Cannot get non initialized texture" );
311 "Can only get image typf" );
312 CORE_ASSERT( m_textureParameters.image.
getTexels() !=
nullptr,
"Can only get image type" );
313 CORE_ASSERT( GL_TEXTURE_CUBE_MAP != m_texture->target(),
"Cannot get cube map" );
315 m_texture->getImage( level,
316 m_textureParameters.image.format,
317 m_textureParameters.image.type,
318 m_textureParameters.image.getImage().
get() );
323 switch ( m_texture->target() ) {
324 case GL_TEXTURE_CUBE_MAP:
326 m_texture->setParameter( GL_TEXTURE_WRAP_R, m_textureParameters.sampler.
wrapR );
330 case GL_TEXTURE_RECTANGLE:
331 m_texture->setParameter( GL_TEXTURE_WRAP_T, m_textureParameters.sampler.
wrapT );
335 m_texture->setParameter( GL_TEXTURE_WRAP_S, m_textureParameters.sampler.
wrapS );
341 m_texture->setParameter( GL_TEXTURE_MIN_FILTER, m_textureParameters.sampler.
minFilter );
343 m_texture->setParameter( GL_TEXTURE_MAG_FILTER, m_textureParameters.sampler.
magFilter );
348void Texture::srgbToLinearRgb( uint8_t* texels,
353 bool hasAlphaChannel ) {
355 auto linearize = []( uint8_t in ) -> uint8_t {
357 float c = float( in ) / 255;
358 if ( c < 0.04045 ) { c = c / 12.92f; }
359 else { c =
std::pow( ( ( c + 0.055f ) / ( 1.055f ) ), 2.4f ); }
360 return uint8_t( c * 255 );
362 uint numValues = hasAlphaChannel ? numComponent - 1 : numComponent;
363#pragma omp parallel for
364 for (
int i = 0; i < int( width * height * depth ); ++i ) {
366 for ( uint p = i * numComponent; p < i * numComponent + numValues; ++p ) {
372void Texture::linearizeCubeMap( ImageParameters& image, uint numComponent,
bool hasAlphaChannel ) {
373 if ( image.type == gl::GLenum::GL_UNSIGNED_BYTE ) {
376 const auto cubeMap = image.getCubeMap();
377 for (
int i = 0; i < 6; ++i ) {
378 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.