png: always expand 3-byte-per-pixel textures as 4-byte-per-pixel

This commit is contained in:
Zack Buhman 2026-07-25 22:08:36 -05:00
parent 96636d1cb1
commit ed2160a935
3 changed files with 26 additions and 33 deletions

View File

@ -95,5 +95,5 @@ fn fragmentMain(input: FragmentInput) -> @location(0) vec4f
let intensity = lighting(input.positionWorld, normalize(input.normal)); let intensity = lighting(input.positionWorld, normalize(input.normal));
let color = textureSample(colorTexture, linearSampler, input.texture); let color = textureSample(colorTexture, linearSampler, input.texture);
return vec4(color.xyz * intensity, 1.0); return vec4(color.xyz, 1.0);
} }

View File

@ -278,15 +278,6 @@ function memoryString(memory, offset)
return new TextDecoder().decode(new Uint8Array(s)); return new TextDecoder().decode(new Uint8Array(s));
} }
function pngComponents(colorType)
{
if (colorType == 2)
return 3;
if (colorType == 6)
return 4;
throw new Error("non-implemented png color type");
}
async function loadTextures(device, memory, module, gltf) async function loadTextures(device, memory, module, gltf)
{ {
const tempTable = module.instance.exports.mem_alloc(256 * 4); const tempTable = module.instance.exports.mem_alloc(256 * 4);
@ -326,11 +317,6 @@ async function loadTextures(device, memory, module, gltf)
const width = tempHeaderU32[0]; const width = tempHeaderU32[0];
const height = tempHeaderU32[1]; const height = tempHeaderU32[1];
const bitDepth = tempHeaderU32[2];
const colorType = tempHeaderU32[3];
const components = pngComponents(colorType);
console.log(components);
const texture = device.createTexture({ const texture = device.createTexture({
size: [width, height], size: [width, height],
format: 'rgba8unorm', format: 'rgba8unorm',
@ -339,7 +325,7 @@ async function loadTextures(device, memory, module, gltf)
device.queue.writeTexture({ texture: texture }, device.queue.writeTexture({ texture: texture },
tempOutputU8, tempOutputU8,
{ bytesPerRow: width * components }, { bytesPerRow: width * 4 },
{ width: width, height: height }); { width: width, height: height });
textures.push(texture); textures.push(texture);
@ -368,7 +354,7 @@ async function loadGltf(device, canvasFormat, memory, module)
code: await code, code: await code,
}); });
const renderer = new GltfRenderer(device, canvasFormat, shaderModule, gltf, textures[2]); const renderer = new GltfRenderer(device, canvasFormat, shaderModule, gltf, textures[0]);
console.log(renderer.nodeBuffer); console.log(renderer.nodeBuffer);
device.queue.writeBuffer(renderer.nodeBuffer, 0, device.queue.writeBuffer(renderer.nodeBuffer, 0,
memory.buffer, nodesHandle, (4 * 4 * 4) * gltf.json.nodes.length); memory.buffer, nodesHandle, (4 * 4 * 4) * gltf.json.nodes.length);

View File

@ -104,9 +104,11 @@ static int buffer_get(uint8_t const * buf, int stride, int x, int y)
static int reconstruct(int function, static int reconstruct(int function,
uint8_t const * ibuf, int istride, uint8_t const * ibuf, int istride,
uint8_t const * obuf, int ostride, uint8_t const * obuf, int ostride,
int x, int y, int cpp) int ix, int y,
int ox,
int ocpp)
{ {
int f = ibuf[y * istride + x + 1]; int f = ibuf[y * istride + ix + 1];
switch (function) { switch (function) {
case 0: // none case 0: // none
{ {
@ -114,25 +116,25 @@ static int reconstruct(int function,
} }
case 1: // sub case 1: // sub
{ {
int a = buffer_get(obuf, ostride, x - cpp, y); int a = buffer_get(obuf, ostride, ox - ocpp, y);
return (f + a) & 0xff; return (f + a) & 0xff;
} }
case 2: // up case 2: // up
{ {
int b = buffer_get(obuf, ostride, x, y - 1); int b = buffer_get(obuf, ostride, ox, y - 1);
return (f + b) & 0xff; return (f + b) & 0xff;
} }
case 3: // average case 3: // average
{ {
int a = buffer_get(obuf, ostride, x - cpp, y); int a = buffer_get(obuf, ostride, ox - ocpp, y);
int b = buffer_get(obuf, ostride, x, y - 1); int b = buffer_get(obuf, ostride, ox, y - 1);
return (f + ((a + b) / 2)) & 0xff; return (f + ((a + b) / 2)) & 0xff;
} }
case 4: // paeth case 4: // paeth
{ {
int a = buffer_get(obuf, ostride, x - cpp, y); int a = buffer_get(obuf, ostride, ox - ocpp, y);
int b = buffer_get(obuf, ostride, x, y - 1); int b = buffer_get(obuf, ostride, ox, y - 1);
int c = buffer_get(obuf, ostride, x - cpp, y - 1); int c = buffer_get(obuf, ostride, ox - ocpp, y - 1);
return (f + paeth(a, b, c)) & 0xff; return (f + paeth(a, b, c)) & 0xff;
} }
default: default:
@ -230,22 +232,27 @@ static int decode_iend(uint32_t length,
return -(22 | (header->bit_depth << 8)); return -(22 | (header->bit_depth << 8));
} }
int cpp = components_per_pixel(header); int icpp = components_per_pixel(header);
if (cpp < 0) { if (icpp < 0) {
state->error = "unsupported color type"; state->error = "unsupported color type";
return -(3 | (header->color_type << 8)); return -(3 | (header->color_type << 8));
} }
int obpp = cpp * 1; int ocpp = 4;
int obpp = ocpp * 1;
int ostride = header->width * obpp; int ostride = header->width * obpp;
int ibpp = cpp * 1; int ibpp = icpp * 1;
int istride = header->width * ibpp + 1; int istride = header->width * ibpp + 1;
for (int y = 0; y < header->height; y++) { for (int y = 0; y < header->height; y++) {
int function = state->ibuf[y * istride]; int function = state->ibuf[y * istride];
for (int x = 0; x < header->width * cpp; x++) { for (int x = 0; x < header->width; x++) {
int value = reconstruct(function, state->ibuf, istride, obuf, ostride, x, y, cpp); for (int c = 0; c < icpp; c++) {
obuf[y * ostride + x] = value; int ix = x * icpp + c;
int ox = x * ocpp + c;
int value = reconstruct(function, state->ibuf, istride, obuf, ostride, ix, y, ox, ocpp);
obuf[y * ostride + ox] = value;
}
} }
} }