Visual Computing Library  devel
Loading...
Searching...
No Matches
texture.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2026 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_BGFX_TEXTURE_H
24#define VCL_BGFX_TEXTURE_H
25
26#include <vclib/base.h>
27#include <vclib/space/core.h>
28
29#include <vclib/bgfx/context.h>
30
31#include <bgfx/bgfx.h>
32#include <bimg/bimg.h>
33
34namespace vcl {
35
45{
46 bgfx::TextureHandle mTextureHandle = BGFX_INVALID_HANDLE;
47
48public:
55 Texture() = default;
56
63 Texture(const Texture& other) = delete;
64
73 Texture(Texture&& other) noexcept { swap(other); }
74
82 {
83 if (bgfx::isValid(mTextureHandle))
84 bgfx::destroy(mTextureHandle);
85 }
86
93 Texture& operator=(const Texture& other) = delete;
94
105 {
106 swap(other);
107 return *this;
108 }
109
116 {
117 using std::swap;
118 swap(mTextureHandle, other.mTextureHandle);
119 }
120
126 friend void swap(Texture& a, Texture& b) { a.swap(b); }
127
133 bool isValid() const { return bgfx::isValid(mTextureHandle); }
134
145 void set(const bimg::ImageContainer& image, bool hasMips, uint64_t flags)
146 {
147 const bool imageHasAlreadyMips = image.m_numMips > 1;
148 const bool passDataDirectly =
150
151 if (bgfx::isValid(mTextureHandle))
152 bgfx::destroy(mTextureHandle);
153
154 if (passDataDirectly) {
155 const uint8_t* imageData = (uint8_t*) image.m_data;
156
157 if (image.m_cubeMap) {
158 mTextureHandle = bgfx::createTextureCube(
159 image.m_width,
160 hasMips,
161 image.m_numLayers,
162 bgfx::TextureFormat::Enum(image.m_format),
163 flags,
164 bgfxCopyMemory(imageData, image.m_size));
165 }
166 else {
167 mTextureHandle = bgfx::createTexture2D(
168 image.m_width,
169 image.m_height,
170 hasMips,
171 image.m_numLayers,
172 bgfx::TextureFormat::Enum(image.m_format),
173 flags,
174 bgfxCopyMemory(imageData, image.m_size));
175 }
176 }
177 else {
178 // Image has not mips but we still want to allocate the related
179 // memory. For this we need to actually create an empty texture and
180 // update it manually to avoid undefined behavior.
181
182 if (image.m_cubeMap) {
183 mTextureHandle = bgfx::createTextureCube(
184 image.m_width,
185 hasMips,
186 image.m_numLayers,
187 bgfx::TextureFormat::Enum(image.m_format),
188 flags);
189
190 for (uint8_t face = 0; face < 6; face++)
191 copyMip0ToTexture(image, face);
192 }
193 else {
194 mTextureHandle = bgfx::createTexture2D(
195 image.m_width,
196 image.m_height,
197 hasMips,
198 image.m_numLayers,
199 bgfx::TextureFormat::Enum(image.m_format),
200 flags);
201
202 copyMip0ToTexture(image);
203 }
204 }
205 }
206
222 void set(
223 const void* data,
224 const vcl::Point2i& size,
225 bool hasMips = false,
227 bgfx::TextureFormat::Enum format = bgfx::TextureFormat::RGBA8,
228 bool isCubemap = false,
229 bgfx::ReleaseFn releaseFn = nullptr)
230 {
231 uint32_t sz = bimg::imageGetSize(
232 nullptr,
233 size.x(),
234 size.y(),
235 1,
236 isCubemap,
237 hasMips,
238 1,
239 // there is correspondence between bimg and bgfx texture formats
240 static_cast<bimg::TextureFormat::Enum>(toUnderlying(format)));
241 set(bgfx::makeRef(data, sz, releaseFn),
242 size,
243 hasMips,
244 1,
245 format,
246 isCubemap,
247 flags);
248 }
249
267 void set(
268 const bgfx::Memory* texture,
269 const vcl::Point2i& size,
270 bool hasMips,
272 bgfx::TextureFormat::Enum format = bgfx::TextureFormat::RGBA8,
273 bool isCubemap = false,
275 {
276 if (bgfx::isValid(mTextureHandle))
277 bgfx::destroy(mTextureHandle);
278
279 if (isCubemap)
280 mTextureHandle = bgfx::createTextureCube(
281 size.x(), hasMips, nLayers, format, flags, texture);
282 else
283 mTextureHandle = bgfx::createTexture2D(
284 size.x(), size.y(), hasMips, nLayers, format, flags, texture);
285 }
286
299 void bind(
300 uint stage,
301 bgfx::UniformHandle samplerHandle,
303 {
304 if (bgfx::isValid(mTextureHandle) && bgfx::isValid(samplerHandle)) {
305 bgfx::setTexture(
306 stage, samplerHandle, mTextureHandle, samplerFlags);
307 }
308 }
309
319 uint stage,
320 uint mip,
321 bgfx::Access::Enum access,
322 bgfx::TextureFormat::Enum format = bgfx::TextureFormat::Count) const
323 {
324 if (bgfx::isValid(mTextureHandle))
325 bgfx::setImage(stage, mTextureHandle, mip, access, format);
326 }
327
337 {
340
341 uint flags = BGFX_SAMPLER_NONE;
342
343 // set minification filter - bgfx default is linear
344 if (tex.minFilter() == NEAREST ||
345 tex.minFilter() == NEAREST_MIPMAP_LINEAR ||
346 tex.minFilter() == NEAREST_MIPMAP_NEAREST)
347 flags |= BGFX_SAMPLER_MIN_POINT;
348
349 // set mipmap filter - bgfx default is linear
350 if (tex.minFilter() == NEAREST_MIPMAP_NEAREST ||
351 tex.minFilter() == LINEAR_MIPMAP_NEAREST)
352 flags |= BGFX_SAMPLER_MIP_POINT;
353
354 // set magnification filter - bgfx default is linear
356 flags |= BGFX_SAMPLER_MAG_POINT;
357
358 // set wrap modes - bgfx default is repeat
359 if (tex.wrapU() == CLAMP_TO_EDGE)
360 flags |= BGFX_SAMPLER_U_CLAMP;
361 else if (tex.wrapU() == MIRRORED_REPEAT)
362 flags |= BGFX_SAMPLER_U_MIRROR;
363
364 if (tex.wrapV() == CLAMP_TO_EDGE)
365 flags |= BGFX_SAMPLER_V_CLAMP;
366 else if (tex.wrapV() == MIRRORED_REPEAT)
367 flags |= BGFX_SAMPLER_V_MIRROR;
368
369 return flags;
370 }
371
372private:
373 void copyMip0ToTexture(const bimg::ImageContainer& image, uint8_t face = 0)
374 {
375 bimg::ImageMip mip;
376 bimg::imageGetRawData(image, face, 0, image.m_data, image.m_size, mip);
377
378 if (image.m_cubeMap) {
379 bgfx::updateTextureCube(
380 mTextureHandle,
381 0,
382 face,
383 0,
384 0,
385 0,
386 mip.m_width,
387 mip.m_height,
388 bgfxCopyMemory(mip.m_data, mip.m_size));
389 }
390 else {
391 bgfx::updateTexture2D(
392 mTextureHandle,
393 0,
394 0,
395 0,
396 0,
397 mip.m_width,
398 mip.m_height,
399 bgfxCopyMemory(mip.m_data, mip.m_size));
400 }
401 }
402
403 static const bgfx::Memory* bgfxCopyMemory(
404 const uint8_t* data,
405 uint32_t size)
406 {
407 auto [buffer, releaseFn] =
408 Context::getAllocatedBufferAndReleaseFn<uint8_t>(size);
409
410 std::copy(data, data + size, buffer);
411
412 return bgfx::makeRef(buffer, size, releaseFn);
413 }
414};
415
416} // namespace vcl
417
418#endif // VCL_BGFX_TEXTURE_H
The Point class represents an N-dimensional point containing N scalar values.
Definition point.h:55
ScalarType & x()
Returns a reference to the x-component of the Point object.
Definition point.h:128
ScalarType & y()
Returns a reference to the y-component of the Point object.
Definition point.h:150
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:41
Describes the properties of a texture, such as its source path and rendering parameters.
Definition texture_descriptor.h:42
MinificationFilter
Defines the texture minification filter modes, following the glTF 2.0 specification....
Definition texture_descriptor.h:50
@ NEAREST
Nearest neighbor filtering.
WrapMode
Defines the texture wrapping modes for S (U) and T (V) coordinates, following the glTF 2....
Definition texture_descriptor.h:81
Manages a BGFX texture.
Definition texture.h:45
bool isValid() const
Checks if the Texture holds valid BGFX texture handle.
Definition texture.h:133
void bindForCompute(uint stage, uint mip, bgfx::Access::Enum access, bgfx::TextureFormat::Enum format=bgfx::TextureFormat::Count) const
Binds the texture to a texture stage for compute shaders.
Definition texture.h:318
Texture(const Texture &other)=delete
Deleted copy constructor.
Texture & operator=(Texture &&other) noexcept
Move assignment operator.
Definition texture.h:104
void set(const bgfx::Memory *texture, const vcl::Point2i &size, bool hasMips, uint nLayers, bgfx::TextureFormat::Enum format=bgfx::TextureFormat::RGBA8, bool isCubemap=false, uint64_t flags=BGFX_TEXTURE_NONE|BGFX_SAMPLER_NONE)
Creates a 2D texture from a bgfx::Memory reference.
Definition texture.h:267
friend void swap(Texture &a, Texture &b)
Swaps two Texture objects.
Definition texture.h:126
Texture & operator=(const Texture &other)=delete
Deleted copy assignment operator.
void set(const bimg::ImageContainer &image, bool hasMips, uint64_t flags)
Creates a texture from a bgfx::ImageContainer.
Definition texture.h:145
Texture()=default
Default constructor.
static uint samplerFlagsFromTexture(const TextureDescriptor &tex)
Generates BGFX sampler flags based on the texture's filtering and wrapping modes.
Definition texture.h:336
void swap(Texture &other)
Swaps the content of this object with another Texture.
Definition texture.h:115
Texture(Texture &&other) noexcept
Move constructor.
Definition texture.h:73
~Texture()
Destructor.
Definition texture.h:81
void bind(uint stage, bgfx::UniformHandle samplerHandle, uint samplerFlags=UINT32_MAX) const
Binds the texture to a texture stage for rendering.
Definition texture.h:299
void set(const void *data, const vcl::Point2i &size, bool hasMips=false, uint64_t flags=BGFX_TEXTURE_NONE|BGFX_SAMPLER_NONE, bgfx::TextureFormat::Enum format=bgfx::TextureFormat::RGBA8, bool isCubemap=false, bgfx::ReleaseFn releaseFn=nullptr)
Creates a 2D texture from raw pixel data.
Definition texture.h:222