1 #include <Core/Tasks/Task.hpp>
2 #include <Core/Tasks/TaskQueue.hpp>
3 #include <Core/Utils/Log.hpp>
4 #include <Engine/Data/Texture.hpp>
5 #include <Engine/RadiumEngine.hpp>
7 #include <globjects/Texture.h>
14 using namespace Core::Utils;
17 m_textureParameters { texParameters },
18 m_texture { nullptr },
19 m_isMipMapped { false },
20 m_isLinear { false } {}
23 if ( m_updateDataTaskId.isValid() ) {
24 RadiumEngine::getInstance()->removeGpuTask( m_updateDataTaskId );
29 if ( ( m_textureParameters.
target != GL_TEXTURE_1D ) &&
30 ( m_textureParameters.
target != GL_TEXTURE_2D ) &&
31 ( m_textureParameters.
target != GL_TEXTURE_RECTANGLE ) &&
32 ( m_textureParameters.
target != GL_TEXTURE_3D ) &&
33 ( m_textureParameters.
target != GL_TEXTURE_CUBE_MAP ) ) {
34 LOG( logERROR ) <<
"Texture of type " << m_textureParameters.
target
35 <<
" must be generated explicitly!";
41 bool hasAlpha =
false;
42 switch ( m_textureParameters.
format ) {
60 LOG( logERROR ) <<
"Textures with format " << m_textureParameters.
format
61 <<
" can't be linearized." << m_textureParameters.
name;
64 if ( m_textureParameters.
target == GL_TEXTURE_CUBE_MAP ) {
65 linearizeCubeMap( numComp, hasAlpha );
70 reinterpret_cast<uint8_t*
>( m_textureParameters.
texels ), numComp, hasAlpha );
74 if ( m_texture ==
nullptr ) {
75 m_texture = globjects::Texture::create( m_textureParameters.
target );
79 m_isMipMapped = !( m_textureParameters.
minFilter == GL_NEAREST ||
80 m_textureParameters.
minFilter == GL_LINEAR );
85 if ( m_isMipMapped ) { m_texture->generateMipmap(); }
89 if ( unit >= 0 ) { m_texture->bindActive( uint( unit ) ); }
90 else { m_texture->bind(); }
98 m_texture->bindImageTexture(
99 uint( unit ), level, layered, layer, access, m_textureParameters.
internalFormat );
102 void Texture::updateGL() {
103 CORE_ASSERT( m_texture !=
nullptr,
"Cannot update non initialized texture" );
104 switch ( m_texture->target() ) {
105 case GL_TEXTURE_1D: {
106 m_texture->image1D( 0,
108 GLsizei( m_textureParameters.
width ),
110 m_textureParameters.
format,
111 m_textureParameters.
type,
112 m_textureParameters.
texels );
116 case GL_TEXTURE_RECTANGLE: {
117 m_texture->image2D( 0,
119 GLsizei( m_textureParameters.
width ),
120 GLsizei( m_textureParameters.
height ),
122 m_textureParameters.
format,
123 m_textureParameters.
type,
124 m_textureParameters.
texels );
127 case GL_TEXTURE_3D: {
128 m_texture->image3D( 0,
130 GLsizei( m_textureParameters.
width ),
131 GLsizei( m_textureParameters.
height ),
132 GLsizei( m_textureParameters.
depth ),
134 m_textureParameters.
format,
135 m_textureParameters.
type,
136 m_textureParameters.
texels );
139 case GL_TEXTURE_CUBE_MAP: {
141 static const void* nullTexels[6] {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr };
142 auto texels = m_textureParameters.
texels !=
nullptr
143 ? (
const void**)m_textureParameters.
texels
149 gl::glTexImage2D( gl::GL_TEXTURE_CUBE_MAP_POSITIVE_X,
152 GLsizei( m_textureParameters.
width ),
153 GLsizei( m_textureParameters.
height ),
155 m_textureParameters.
format,
156 m_textureParameters.
type,
158 gl::glTexImage2D( gl::GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
161 GLsizei( m_textureParameters.
width ),
162 GLsizei( m_textureParameters.
height ),
164 m_textureParameters.
format,
165 m_textureParameters.
type,
168 gl::glTexImage2D( gl::GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
171 GLsizei( m_textureParameters.
width ),
172 GLsizei( m_textureParameters.
height ),
174 m_textureParameters.
format,
175 m_textureParameters.
type,
177 gl::glTexImage2D( gl::GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
180 GLsizei( m_textureParameters.
width ),
181 GLsizei( m_textureParameters.
height ),
183 m_textureParameters.
format,
184 m_textureParameters.
type,
187 gl::glTexImage2D( gl::GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
190 GLsizei( m_textureParameters.
width ),
191 GLsizei( m_textureParameters.
height ),
193 m_textureParameters.
format,
194 m_textureParameters.
type,
196 gl::glTexImage2D( gl::GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
199 GLsizei( m_textureParameters.
width ),
200 GLsizei( m_textureParameters.
height ),
202 m_textureParameters.
format,
203 m_textureParameters.
type,
210 CORE_ASSERT( 0,
"Unsupported texture type ?" );
218 std::lock_guard<std::mutex> lock( m_updateMutex );
220 m_textureParameters.
texels = newData;
222 if ( m_updateDataTaskId.isInvalid() ) {
223 auto taskFunc = [
this]() {
224 std::lock_guard<std::mutex> taskLock( m_updateMutex );
226 m_updateDataTaskId = Core::TaskQueue::TaskId::Invalid();
228 auto task = std::make_unique<Core::FunctionTask>( taskFunc,
getName() );
229 m_updateDataTaskId = RadiumEngine::getInstance()->addGpuTask( std::move( task ) );
235 switch ( m_texture->target() ) {
236 case GL_TEXTURE_CUBE_MAP:
238 m_texture->setParameter( GL_TEXTURE_WRAP_R, m_textureParameters.
wrapP );
242 case GL_TEXTURE_RECTANGLE:
243 m_texture->setParameter( GL_TEXTURE_WRAP_T, m_textureParameters.
wrapT );
247 m_texture->setParameter( GL_TEXTURE_WRAP_S, m_textureParameters.
wrapS );
253 m_texture->setParameter( GL_TEXTURE_MIN_FILTER, m_textureParameters.
minFilter );
255 m_texture->setParameter( GL_TEXTURE_MAG_FILTER, m_textureParameters.
magFilter );
260 if ( m_texture !=
nullptr ) {
261 LOG( logERROR ) <<
"Only non OpenGL initialized texture can be linearized.";
267 bool hasAlpha =
false;
268 switch ( m_textureParameters.
format ) {
281 LOG( logERROR ) <<
"Textures with format " << m_textureParameters.
format
282 <<
" can't be linearized." << m_textureParameters.
name;
285 sRGBToLinearRGB(
reinterpret_cast<uint8_t*
>( m_textureParameters.
texels ), numComp, hasAlpha );
288 void Texture::sRGBToLinearRGB( uint8_t* texels, uint numComponent,
bool hasAlphaChannel ) {
289 std::lock_guard<std::mutex> lock( m_updateMutex );
293 auto linearize = []( uint8_t in ) -> uint8_t {
295 float c = float( in ) / 255;
296 if ( c < 0.04045 ) { c = c / 12.92f; }
297 else { c = std::pow( ( ( c + 0.055f ) / ( 1.055f ) ), 2.4f ); }
298 return uint8_t( c * 255 );
300 uint numValues = hasAlphaChannel ? numComponent - 1 : numComponent;
301 #pragma omp parallel for
302 for (
int i = 0; i < int( m_textureParameters.
width * m_textureParameters.
height *
303 m_textureParameters.
depth );
306 for ( uint p = i * numComponent; p < i * numComponent + numValues; ++p ) {
314 m_textureParameters.
width = w;
315 m_textureParameters.
height = h;
316 m_textureParameters.
depth = d;
317 m_textureParameters.
texels = pix;
320 if ( m_isMipMapped ) { m_texture->generateMipmap(); }
323 void Texture::linearizeCubeMap( uint numComponent,
bool hasAlphaChannel ) {
324 if ( m_textureParameters.
type == gl::GLenum::GL_UNSIGNED_BYTE ) {
327 for (
int i = 0; i < 6; ++i ) {
329 reinterpret_cast<uint8_t*
>( ( (
void**)m_textureParameters.
texels )[i] ),
void bind(int unit=-1)
Bind the texture to enable its use in a shader.
void updateData(void *newData)
void initializeGL(bool linearize=false)
Generate the OpenGL representation of the texture according to the stored TextureData.
std::string getName() const
void resize(size_t w=1, size_t h=1, size_t d=1, void *pix=nullptr)
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.
Texture(const Texture &)=delete
GLenum wrapT
OpenGL wrap mode in the t direction.
GLenum magFilter
OpenGL magnification filter ( GL_LINEAR or GL_NEAREST )
GLenum wrapS
OpenGL wrap mode in the s direction.
size_t depth
width of the texture (p dimension)
GLenum wrapP
OpenGL wrap mode in the p direction.
size_t height
height of the texture (t dimension)
GLenum minFilter
OpenGL minification filter ( GL_LINEAR or GL_NEAREST or GL_XXX_MIPMAP_YYY )
GLenum format
Format of the external data.
size_t width
width of the texture (s dimension)
GLenum target
OpenGL target.
GLenum type
Type of the components in external data.
GLenum internalFormat
OpenGL internal format (WARNING, for Integer textures, must be GL_XXX_INTEGER)
std::string name
Name of the texture.