framebuffer tga download
This commit is contained in:
parent
c9a65e3bcf
commit
717e73d32d
@ -9,7 +9,7 @@ function makeSliders()
|
|||||||
const sliders = {
|
const sliders = {
|
||||||
subpixelOptions: new RowHeader("global options"),
|
subpixelOptions: new RowHeader("global options"),
|
||||||
mode: new Select("mode", ["supersampling", "subpixel"]),
|
mode: new Select("mode", ["supersampling", "subpixel"]),
|
||||||
scale: new Slider("scale", 0.0, 0.01),
|
scale: new Slider("scale", 0.0, 0.05),
|
||||||
translateX: new Slider("translate x", -1, 1),
|
translateX: new Slider("translate x", -1, 1),
|
||||||
translateY: new Slider("translate y", -1, 1),
|
translateY: new Slider("translate y", -1, 1),
|
||||||
multisampleCount: new Slider("multisampleCount", 1, 4, 1),
|
multisampleCount: new Slider("multisampleCount", 1, 4, 1),
|
||||||
|
|||||||
@ -65,6 +65,11 @@
|
|||||||
font: 0.8rem sans-serif;
|
font: 0.8rem sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="button"] {
|
||||||
|
width: calc(100% - 1.1em);
|
||||||
|
grid-column: 1 / span 3;
|
||||||
|
}
|
||||||
|
|
||||||
input[type="range"], input[type="text"] {
|
input[type="range"], input[type="text"] {
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
}
|
}
|
||||||
@ -100,6 +105,10 @@
|
|||||||
<control-root>
|
<control-root>
|
||||||
<control-main>
|
<control-main>
|
||||||
<control-grid id="control-parent">
|
<control-grid id="control-parent">
|
||||||
|
<row>
|
||||||
|
<input id="download-framebuffer" type="button" value="download framebuffer"></input>
|
||||||
|
</row>
|
||||||
|
<row-separator></row-separator>
|
||||||
</control-grid>
|
</control-grid>
|
||||||
</control-main>
|
</control-main>
|
||||||
</control-root>
|
</control-root>
|
||||||
|
|||||||
112
index.js
112
index.js
@ -56,6 +56,7 @@ module.memory = memory;
|
|||||||
|
|
||||||
var depthTexture = undefined;
|
var depthTexture = undefined;
|
||||||
var multisampleTexture = undefined;
|
var multisampleTexture = undefined;
|
||||||
|
var copyTexture = undefined;
|
||||||
|
|
||||||
const eyeValueX = document.getElementById("eye-value-x");
|
const eyeValueX = document.getElementById("eye-value-x");
|
||||||
const eyeValueY = document.getElementById("eye-value-y");
|
const eyeValueY = document.getElementById("eye-value-y");
|
||||||
@ -64,6 +65,9 @@ const eyeValueZ = document.getElementById("eye-value-z");
|
|||||||
const yawValue = document.getElementById("yaw");
|
const yawValue = document.getElementById("yaw");
|
||||||
const pitchValue = document.getElementById("pitch");
|
const pitchValue = document.getElementById("pitch");
|
||||||
|
|
||||||
|
var downloadFramebufferPending = false;
|
||||||
|
var tempBuffer = undefined;
|
||||||
|
|
||||||
function recreateDepth(canvasTexture, sampleCount)
|
function recreateDepth(canvasTexture, sampleCount)
|
||||||
{
|
{
|
||||||
const depthResized = depthTexture === undefined || canvasTexture.width != depthTexture.width || canvasTexture.height != depthTexture.height;
|
const depthResized = depthTexture === undefined || canvasTexture.width != depthTexture.width || canvasTexture.height != depthTexture.height;
|
||||||
@ -81,6 +85,33 @@ function recreateDepth(canvasTexture, sampleCount)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tempBufferSize = canvasTexture.width * canvasTexture.height * 4;
|
||||||
|
const tempResized = tempBuffer === undefined || tempBufferSize != tempBuffer.size;
|
||||||
|
if (tempResized) {
|
||||||
|
if (tempBuffer !== undefined) {
|
||||||
|
tempBuffer.destroy();
|
||||||
|
}
|
||||||
|
tempBuffer = device.createBuffer({
|
||||||
|
label: "temp buffer",
|
||||||
|
size: tempBufferSize,
|
||||||
|
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const copyResized = copyTexture === undefined || canvasTexture.width !== copyTexture.width || canvasTexture.height !== copyTexture.height;
|
||||||
|
if (copyResized) {
|
||||||
|
if (copyTexture !== undefined) {
|
||||||
|
copyTexture.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
copyTexture = device.createTexture({
|
||||||
|
format: canvasTexture.format,
|
||||||
|
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
|
||||||
|
size: [canvasTexture.width, canvasTexture.height],
|
||||||
|
sampleCount: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (sampleCount > 1) {
|
if (sampleCount > 1) {
|
||||||
const multisampleResized = multisampleTexture === undefined || canvasTexture.width !== multisampleTexture.width || canvasTexture.height !== multisampleTexture.height;
|
const multisampleResized = multisampleTexture === undefined || canvasTexture.width !== multisampleTexture.width || canvasTexture.height !== multisampleTexture.height;
|
||||||
if (multisampleResized || multisampleTexture.sampleCount !== sampleCount) {
|
if (multisampleResized || multisampleTexture.sampleCount !== sampleCount) {
|
||||||
@ -177,9 +208,18 @@ function handleKeyup(e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleDownloadButton(e)
|
||||||
|
{
|
||||||
|
downloadFramebufferPending = true;
|
||||||
|
console.log("download framebuffer");
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener('keydown', handleKeydown, false);
|
window.addEventListener('keydown', handleKeydown, false);
|
||||||
window.addEventListener('keyup', handleKeyup, false);
|
window.addEventListener('keyup', handleKeyup, false);
|
||||||
|
|
||||||
|
const downloadFramebufferButton = document.getElementById("download-framebuffer");
|
||||||
|
downloadFramebufferButton.addEventListener("click", handleDownloadButton, false);
|
||||||
|
|
||||||
function updateView()
|
function updateView()
|
||||||
{
|
{
|
||||||
const lu = keyState[KEY.W] === true;
|
const lu = keyState[KEY.W] === true;
|
||||||
@ -260,7 +300,30 @@ canvas.addEventListener("mousemove", onMouseMove);
|
|||||||
var canRender = false;
|
var canRender = false;
|
||||||
var frameNumber = 0;
|
var frameNumber = 0;
|
||||||
|
|
||||||
var tempBuffer = undefined;
|
function tgaBlob(texture, mappedRange)
|
||||||
|
{
|
||||||
|
const tgaHeaderSize = 18;
|
||||||
|
const tgaBuffer = new ArrayBuffer(mappedRange.byteLength + tgaHeaderSize);
|
||||||
|
const tgaView = new DataView(tgaBuffer);
|
||||||
|
tgaView.setUint8(0, 0); // idLength
|
||||||
|
tgaView.setUint8(1, 0); // colorMapType
|
||||||
|
tgaView.setUint8(2, 2); // imageTypeCode: 2 uncompressed RGB
|
||||||
|
tgaView.setUint16(3, 0, true); // colorMap origin
|
||||||
|
tgaView.setUint16(5, 0, true); // colorMap length
|
||||||
|
tgaView.setUint8(7, 0); // colorMap depth
|
||||||
|
tgaView.setUint16(8, 0, true); // xOrigin
|
||||||
|
tgaView.setUint16(10, 0, true); // yOrigin
|
||||||
|
tgaView.setUint16(12, texture.width, true); // width
|
||||||
|
tgaView.setUint16(14, texture.height, true); // height
|
||||||
|
tgaView.setUint8(16, 32); // bits per pixel
|
||||||
|
const descriptor = ((8 << 0) | // number of attribute bits
|
||||||
|
(1 << 5) | // origin in upper left
|
||||||
|
(0 << 6)); // non-interleaved
|
||||||
|
tgaView.setUint8(17, descriptor); // descriptor
|
||||||
|
const tgaU8 = new Uint8Array(tgaBuffer);
|
||||||
|
tgaU8.set(new Uint8Array(mappedRange), 18);
|
||||||
|
return new Blob([tgaBuffer]);
|
||||||
|
}
|
||||||
|
|
||||||
function render2()
|
function render2()
|
||||||
{
|
{
|
||||||
@ -281,16 +344,19 @@ function render2()
|
|||||||
|
|
||||||
updateView();
|
updateView();
|
||||||
|
|
||||||
const clearValue = { r: 0.2, g: 0.2, b: 0.4, a: 1.0 };
|
//const clearValue = ;
|
||||||
|
const clearValue = (downloadFramebufferPending) ? { r: 0.0, g: 0.0, b: 0.0, a: 0.0 } : { r: 0.2, g: 0.2, b: 0.4, a: 1.0 };
|
||||||
|
|
||||||
|
const viewTexture = (downloadFramebufferPending) ? copyTexture : canvasTexture;
|
||||||
|
|
||||||
const attachment0 = (sampleCount == 1) ? {
|
const attachment0 = (sampleCount == 1) ? {
|
||||||
view: canvasTexture.createView(),
|
view: viewTexture.createView(),
|
||||||
loadOp: "clear",
|
loadOp: "clear",
|
||||||
clearValue: clearValue,
|
clearValue: clearValue,
|
||||||
storeOp: "store",
|
storeOp: "store",
|
||||||
} : {
|
} : {
|
||||||
view: multisampleTexture.createView(),
|
view: multisampleTexture.createView(),
|
||||||
resolveTarget: canvasTexture.createView(),
|
resolveTarget: viewTexture.createView(),
|
||||||
loadOp: "clear",
|
loadOp: "clear",
|
||||||
clearValue: clearValue,
|
clearValue: clearValue,
|
||||||
storeOp: "store",
|
storeOp: "store",
|
||||||
@ -318,44 +384,40 @@ function render2()
|
|||||||
|
|
||||||
renderPass.end();
|
renderPass.end();
|
||||||
|
|
||||||
/*
|
if (downloadFramebufferPending) {
|
||||||
encoder.copyTextureToBuffer({
|
encoder.copyTextureToBuffer({
|
||||||
texture: multisampleTexture,
|
texture: copyTexture,
|
||||||
}, {
|
}, {
|
||||||
buffer: tempBuffer,
|
buffer: tempBuffer,
|
||||||
bytesPerRow: canvasTexture.width * 4 * 4,
|
bytesPerRow: canvasTexture.width * 4,
|
||||||
}, {
|
}, {
|
||||||
width: canvasTexture.width,
|
width: copyTexture.width,
|
||||||
height: canvasTexture.height,
|
height: copyTexture.height,
|
||||||
depthOrArrayLayers: 1,
|
depthOrArrayLayers: 1,
|
||||||
});
|
});
|
||||||
*/
|
}
|
||||||
|
|
||||||
const commandBuffer = encoder.finish();
|
const commandBuffer = encoder.finish();
|
||||||
device.queue.submit([commandBuffer]);
|
device.queue.submit([commandBuffer]);
|
||||||
|
|
||||||
frameNumber = (frameNumber + 1) % 2;
|
frameNumber = (frameNumber + 1) % 2;
|
||||||
|
|
||||||
/*
|
if (downloadFramebufferPending) {
|
||||||
tempBuffer.mapAsync(GPUMapMode.READ).then(() => {
|
tempBuffer.mapAsync(GPUMapMode.READ).then(() => {
|
||||||
const readBuffer = tempBuffer.getMappedRange(); // arraybuffer
|
const mappedRange = tempBuffer.getMappedRange(); // arraybuffer
|
||||||
//console.log(mousePositionClick);
|
const blob = tgaBlob(copyTexture, mappedRange);
|
||||||
const x = mousePositionClick[0];
|
const url = URL.createObjectURL(blob);
|
||||||
const y = mousePositionClick[1];
|
const a = document.createElement("a");
|
||||||
const f32ReadBuffer = new Float32Array(readBuffer);
|
a.setAttribute("href", url);
|
||||||
for (let i = 0; i < 2; i++) {
|
a.setAttribute("download", "framebuffer.tga");
|
||||||
const a = f32ReadBuffer[((y + i) * canvasTexture.width + x) * 4 + 0];
|
a.click();
|
||||||
const b = f32ReadBuffer[((y + i) * canvasTexture.width + x) * 4 + 1];
|
|
||||||
const c = f32ReadBuffer[((y + i) * canvasTexture.width + x) * 4 + 2];
|
|
||||||
const d = f32ReadBuffer[((y + i) * canvasTexture.width + x) * 4 + 3];
|
|
||||||
//console.log(a, b, c, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempBuffer.unmap();
|
tempBuffer.unmap();
|
||||||
requestAnimationFrame(render2);
|
requestAnimationFrame(render2);
|
||||||
});
|
});
|
||||||
*/
|
downloadFramebufferPending = false;
|
||||||
|
} else {
|
||||||
requestAnimationFrame(render2);
|
requestAnimationFrame(render2);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
requestAnimationFrame(render2);
|
requestAnimationFrame(render2);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user