Added an asynchronous resource loading mechanism through App_GetResourcePath and App_ResourceLoaded. Added stb_image.h and used it to parse a .png file loaded from the server and upload it to app.testTexture. There is some ugliness around the edges images with transparency, probably caused by something pre-multiplied alpha related.
This commit is contained in:
88
test_app.c
88
test_app.c
@@ -38,12 +38,94 @@ r32 OscillateBy(u64 timeSource, r32 min, r32 max, u64 periodMs, u64 offset)
|
||||
return min + (max - min) * lerpValue;
|
||||
}
|
||||
|
||||
// +--------------------------------------------------------------+
|
||||
// | Load Resources |
|
||||
// +--------------------------------------------------------------+
|
||||
WASM_EXPORT(App_GetResourcePath) const char* App_GetResourcePath(int resourceIndex)
|
||||
{
|
||||
switch (resourceIndex)
|
||||
{
|
||||
case 0: return "icon_64.png";
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
WASM_EXPORT(App_ResourceLoaded) void App_ResourceLoaded(int resourceIndex, int fileSize, u8* fileBytes)
|
||||
{
|
||||
switch (resourceIndex)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
PrintLine_D("Got resource %d bytes: %p %02X %02X %02X %02X", fileSize, fileBytes, fileBytes[0], fileBytes[1], fileBytes[2], fileBytes[3]);
|
||||
ScratchBegin(scratch); //NOTE: stbi_load_from_memory implicitly allocates from the first scratch arena
|
||||
int imageWidth = 0;
|
||||
int imageHeight = 0;
|
||||
int imageChannelCount = 0;
|
||||
stbi_uc* textureBytes = stbi_load_from_memory(fileBytes, fileSize, &imageWidth, &imageHeight, &imageChannelCount, 4);
|
||||
if (textureBytes != nullptr)
|
||||
{
|
||||
PrintLine_D("Parsed image: %p %dx%d %d channel(s)", textureBytes, imageWidth, imageHeight, imageChannelCount);
|
||||
|
||||
//We need to reverse the rows of pixels so the image is not upside-down
|
||||
//TODO: Replace with GL_UNPACK_FLIP_Y_WEBGL
|
||||
u32 rowWidth = imageWidth * sizeof(u32);
|
||||
u8* tempRowBuffer = AllocArray(u8, scratch, rowWidth);
|
||||
for (int yIndex = 0; yIndex < imageHeight/2; yIndex++)
|
||||
{
|
||||
memcpy(tempRowBuffer, &textureBytes[yIndex * rowWidth], rowWidth);
|
||||
memcpy(&textureBytes[yIndex * rowWidth], &textureBytes[(imageHeight-1 - yIndex) * rowWidth], rowWidth);
|
||||
memcpy(&textureBytes[(imageHeight-1 - yIndex) * rowWidth], tempRowBuffer, rowWidth);
|
||||
}
|
||||
#if 0
|
||||
for (int yIndex = 0; yIndex < imageHeight; yIndex++)
|
||||
{
|
||||
for (int xIndex = 0; xIndex < imageWidth; xIndex++)
|
||||
{
|
||||
u8* pixelPntr = &textureBytes[((yIndex * imageWidth) + xIndex) * sizeof(u32)];
|
||||
r32 alpha = (pixelPntr[3]/255.0f);
|
||||
pixelPntr[0] = (u8)((pixelPntr[0]/255.0f) * alpha * 255.0f);
|
||||
pixelPntr[1] = (u8)((pixelPntr[1]/255.0f) * alpha * 255.0f);
|
||||
pixelPntr[2] = (u8)((pixelPntr[2]/255.0f) * alpha * 255.0f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (app.testTexture != 0) { jsGlDeleteTexture(app.testTexture); }
|
||||
app.testTexture = jsGlCreateTexture();
|
||||
jsGlActiveTexture(GL_TEXTURE0);
|
||||
jsGlBindTexture(GL_TEXTURE_2D, app.testTexture);
|
||||
// jsGlPixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
|
||||
// jsGlPixelStorei(GL_UNPACK_FLIP_Y_WEBGL, true);
|
||||
jsGlTexImage2D(
|
||||
GL_TEXTURE_2D, //bound texture type
|
||||
0, //image level
|
||||
GL_RGBA, //internal format
|
||||
imageWidth, //image width
|
||||
imageHeight, //image height
|
||||
0, //border
|
||||
GL_RGBA, //format
|
||||
GL_UNSIGNED_BYTE, //type
|
||||
imageWidth*imageHeight*sizeof(u32), //dataLength
|
||||
textureBytes //dataPntr
|
||||
);
|
||||
jsGlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
jsGlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
jsGlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
jsGlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
jsGlGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
else { PrintLine_E("Failed to parse %d byte image using stb_image.h!", fileSize); }
|
||||
ScratchEnd(scratch);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
// +--------------------------------------------------------------+
|
||||
// | Initialize |
|
||||
// +--------------------------------------------------------------+
|
||||
WASM_EXPORT(App_Initialize) bool App_Initialize()
|
||||
{
|
||||
InitializeCWasm(Kilobytes(128));
|
||||
InitializeCWasm(Megabytes(2));
|
||||
memset(&app, 0x00, sizeof(app));
|
||||
|
||||
#if 0
|
||||
@@ -60,6 +142,10 @@ WASM_EXPORT(App_Initialize) bool App_Initialize()
|
||||
PrintLine_D("GL_VERSION: \"%s\"", jsGlGetParameterString(scratch, GL_VERSION));
|
||||
PrintLine_D("GL_VENDOR: \"%s\"", jsGlGetParameterString(scratch, GL_VENDOR));
|
||||
|
||||
jsGlEnable(GL_BLEND);
|
||||
jsGlBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
jsGlBlendEquation(GL_FUNC_ADD);
|
||||
|
||||
r32 positions[] = {
|
||||
0.0, 0.0,
|
||||
1.0, 0.0,
|
||||
|
||||
Reference in New Issue
Block a user