mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-28 00:39:02 +08:00
Add WebGPU image loading and displaying example
# Conflicts: # WebGPU_image_loading_screenshot.png
parent
63cc12fb07
commit
7ea19a1818
@ -10,6 +10,7 @@
|
|||||||
- [Example for DirectX12 users](#example-for-directx12-users)
|
- [Example for DirectX12 users](#example-for-directx12-users)
|
||||||
- [Example for SDL_Renderer users](#example-for-sdl_renderer-users)
|
- [Example for SDL_Renderer users](#example-for-sdl_renderer-users)
|
||||||
- [Example for Vulkan users](#example-for-vulkan-users)
|
- [Example for Vulkan users](#example-for-vulkan-users)
|
||||||
|
- [Example for WebGPU users](#example-for-webgpu-users)
|
||||||
- [Loading from Memory](#loading-from-memory)
|
- [Loading from Memory](#loading-from-memory)
|
||||||
- [About Texture Coordinates](#about-texture-coordinates)
|
- [About Texture Coordinates](#about-texture-coordinates)
|
||||||
|
|
||||||
@ -937,11 +938,176 @@ RemoveTexture(&my_texture);
|
|||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
## Example for WebGPU users
|
||||||
|
|
||||||
|
We will here use [stb_image.h](https://github.com/nothings/stb/blob/master/stb_image.h) to load images from disk.
|
||||||
|
|
||||||
|
Add at the top of one of your source file:
|
||||||
|
```cpp
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
// Simple helper function to load an image into a WebGPU texture with common settings
|
||||||
|
bool LoadTextureFromMemory(const void * data,
|
||||||
|
size_t data_size,
|
||||||
|
WGPUDevice device,
|
||||||
|
WGPUQueue queue,
|
||||||
|
WGPUTexture * out_texture,
|
||||||
|
WGPUTextureView * out_texture_view,
|
||||||
|
int * out_width,
|
||||||
|
int * out_height) {
|
||||||
|
// Load image
|
||||||
|
int image_width = 0;
|
||||||
|
int image_height = 0;
|
||||||
|
// Ask stbi to output 4 channels since WebGPU doesn't have 3-channels texture format
|
||||||
|
const int output_channels = 4;
|
||||||
|
void * const image_data = stbi_load_from_memory((const unsigned char *)data,
|
||||||
|
(int)data_size,
|
||||||
|
&image_width,
|
||||||
|
&image_height,
|
||||||
|
NULL,
|
||||||
|
output_channels);
|
||||||
|
if (image_data == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Create a WebGPU texture
|
||||||
|
WGPUTextureDescriptor texture_desc;
|
||||||
|
texture_desc.nextInChain = NULL;
|
||||||
|
texture_desc.label = NULL;
|
||||||
|
texture_desc.usage = WGPUTextureUsage_CopyDst | WGPUTextureUsage_TextureBinding;
|
||||||
|
texture_desc.dimension = WGPUTextureDimension_2D;
|
||||||
|
texture_desc.size.width = (uint32_t)image_width;
|
||||||
|
texture_desc.size.height = (uint32_t)image_height;
|
||||||
|
texture_desc.size.depthOrArrayLayers = 1;
|
||||||
|
texture_desc.format = WGPUTextureFormat_RGBA8Unorm;
|
||||||
|
texture_desc.mipLevelCount = 1;
|
||||||
|
texture_desc.sampleCount = 1;
|
||||||
|
texture_desc.viewFormatCount = 0;
|
||||||
|
texture_desc.viewFormats = NULL;
|
||||||
|
WGPUTexture image_texture = wgpuDeviceCreateTexture(device, &texture_desc);
|
||||||
|
|
||||||
|
// Write loaded data to texture
|
||||||
|
WGPUImageCopyTexture dest;
|
||||||
|
dest.nextInChain = NULL;
|
||||||
|
dest.texture = image_texture;
|
||||||
|
dest.mipLevel = 0;
|
||||||
|
dest.origin.x = 0;
|
||||||
|
dest.origin.y = 0;
|
||||||
|
dest.origin.z = 0;
|
||||||
|
dest.aspect = WGPUTextureAspect_All;
|
||||||
|
|
||||||
|
WGPUTextureDataLayout src;
|
||||||
|
src.nextInChain = NULL;
|
||||||
|
src.offset = 0;
|
||||||
|
src.bytesPerRow = (uint32_t)(output_channels * image_width);
|
||||||
|
src.rowsPerImage = (uint32_t)image_height;
|
||||||
|
|
||||||
|
const size_t bytes = src.bytesPerRow * src.rowsPerImage;
|
||||||
|
WGPUExtent3D write_size;
|
||||||
|
write_size.width = (uint32_t)image_width;
|
||||||
|
write_size.height = (uint32_t)image_height;
|
||||||
|
write_size.depthOrArrayLayers = 1;
|
||||||
|
wgpuQueueWriteTexture(queue, &dest, image_data, bytes, &src, &write_size);
|
||||||
|
|
||||||
|
// Create a WebGPU texture view
|
||||||
|
WGPUTextureViewDescriptor view_desc;
|
||||||
|
view_desc.nextInChain = NULL;
|
||||||
|
view_desc.label = NULL;
|
||||||
|
view_desc.format = WGPUTextureFormat_RGBA8Unorm;
|
||||||
|
view_desc.dimension = WGPUTextureViewDimension_2D;
|
||||||
|
view_desc.baseMipLevel = 0;
|
||||||
|
view_desc.mipLevelCount = 1;
|
||||||
|
view_desc.baseArrayLayer = 0;
|
||||||
|
view_desc.arrayLayerCount = 1;
|
||||||
|
view_desc.aspect = WGPUTextureAspect_All;
|
||||||
|
|
||||||
|
*out_texture = image_texture;
|
||||||
|
*out_texture_view = wgpuTextureCreateView(image_texture, &view_desc);
|
||||||
|
*out_width = image_width;
|
||||||
|
*out_height = image_height;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open and read a file, then forward to LoadTextureFromMemory()
|
||||||
|
bool LoadTextureFromFile(const char * file_name,
|
||||||
|
WGPUDevice device,
|
||||||
|
WGPUQueue queue,
|
||||||
|
WGPUTexture * out_texture,
|
||||||
|
WGPUTextureView * out_texture_view,
|
||||||
|
int * out_width,
|
||||||
|
int * out_height) {
|
||||||
|
FILE * f = fopen(file_name, "rb");
|
||||||
|
if (f == NULL)
|
||||||
|
return false;
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long file_size = ftell(f);
|
||||||
|
if (file_size == -1)
|
||||||
|
return false;
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
void * file_data = IM_ALLOC(file_size);
|
||||||
|
fread(file_data, 1, (size_t)file_size, f);
|
||||||
|
bool ret = LoadTextureFromMemory(file_data,
|
||||||
|
(size_t)file_size,
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
out_texture,
|
||||||
|
out_texture_view,
|
||||||
|
out_width,
|
||||||
|
out_height);
|
||||||
|
IM_FREE(file_data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After initializing a `WGPUDevice` and a `WGPUQueue`, load our texture:
|
||||||
|
```cpp
|
||||||
|
WGPUDevice device = /* ... */;
|
||||||
|
WGPUQueue queue = /* ... */;
|
||||||
|
|
||||||
|
WGPUTexture my_texture = NULL;
|
||||||
|
WGPUTextureView my_texture_view = NULL;
|
||||||
|
int my_image_width = 0;
|
||||||
|
int my_image_height = 0;
|
||||||
|
bool ret = LoadTextureFromFile("../../MyImage01.jpg",
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
&my_texture,
|
||||||
|
&my_texture_view,
|
||||||
|
&my_image_width,
|
||||||
|
&my_image_height);
|
||||||
|
IM_ASSERT(ret);
|
||||||
|
```
|
||||||
|
|
||||||
|
In the snippet of code above, we added an assert `IM_ASSERT(ret)` to check if the image file was loaded correctly. You may also use your Debugger and confirm that `my_image_texture` is not zero and that `my_image_width` `my_image_height` are correct.
|
||||||
|
|
||||||
|
Now that we have a WebGPU texture view and its dimensions, we can display it in our main loop:
|
||||||
|
```cpp
|
||||||
|
ImGui::Begin("WebGPU Texture Test");
|
||||||
|
ImGui::Text("pointer = %p", my_texture_view);
|
||||||
|
ImGui::Text("size = %d x %d", my_image_width, my_image_height);
|
||||||
|
ImGui::Image((void *)my_texture_view, ImVec2(my_image_width, my_image_height));
|
||||||
|
ImGui::End();
|
||||||
|
```
|
||||||
|
|
||||||
|
Don't forget to clean the memory at the end of the program:
|
||||||
|
```cpp
|
||||||
|
wgpuTextureViewRelease(my_texture_view);
|
||||||
|
wgpuTextureRelease(my_texture);
|
||||||
|
```
|
||||||
|
|
||||||
|
![image](WebGPU_image_loading_screenshot.png)
|
||||||
|
|
||||||
|
##### [Return to Index](#index)
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Loading from Memory
|
## Loading from Memory
|
||||||
|
|
||||||
If instead of loading from a file you would like to load from memory, you can call `stbi_load_from_memory()` instead of `stbi_load()`.
|
If instead of loading from a file you would like to load from memory, you can call `stbi_load_from_memory()` instead of `stbi_load()`.
|
||||||
All `LoadTextureFromFile()` function could be reworked to call `LoadTextureFromMemory()` which contains most of the code.
|
All `LoadTextureFromFile()` function could be reworked to call `LoadTextureFromMemory()` which contains most of the code.
|
||||||
See our implementation of `LoadTextureFromFile()` for OpenGL, DX11 and DX12 examples.
|
See our implementation of `LoadTextureFromFile()` for OpenGL, DX11, DX12 and WebGPU examples.
|
||||||
|
|
||||||
##### [Return to Index](#index)
|
##### [Return to Index](#index)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user