gpt4 book ai didi

javascript - gl.texImage2D 适用于 Image,但不适用于 ImageData

转载 作者:行者123 更新时间:2023-12-03 01:45:21 25 4
gpt4 key购买 nike

当我将 gl.texImage2D 与 javascript 的 Image 对象一起使用来指定像素数据时,我的纹理可以正确渲染。但是,如果我将 Image 渲染到离屏 Canvas ,然后从中提取 ImageData 对象,然后将其提供给 gl.texImage2D > 相反,纹理无法正确绘制。当我检查 ImageData 对象时,像素数据是正确的。 gl.texImage2DImage 对象的处理与对 ImageData 对象的处理有何不同?

图像只是 32 位,每个组件 8 位,RGBA。我的片段着色器获取并期望这些组件作为 [0,1] 中的值。难道当我传入 ImageData 对象时,我的着色器现在将它们获取到 [0,255] 范围内?我必须检验这个假设。无论如何,我完全不知所措。

编辑:经过一番努力,我发现 OpenGL 和着色器管道没有任何问题。我面临的问题与从图像到图像数据的转换有关。这是一些代码...

let perm_image = new Image();
...
let canvas = document.createElement('canvas');
let context = canvas.getContext('2d');
canvas.width = perm_image.width;
canvas.height = perm_image.height;
context.drawImage(perm_image, 0, 0);
let perm_image_data = context.getImageData(0, 0, perm_image.width, perm_image.height);

我将返回的图像数据与实际图像数据进行了比较,虽然缓冲区的第一部分看起来正确,但其余部分是错误的。我以前做过这项检查,但很快就停止了。

无论如何,我将四处看看如何更改/修复上述代码。

最终编辑:我决定放弃。据我所知,没有一种万无一失的方法可以从 JS Image 对象中获取原始的、未更改的 RGBA 数据,我认为无论是谁发明了那个该死的对象,这都是彻底的失败。我要做的只是不使用 PNG 文件,而是使用我自己的二进制格式。

最佳答案

似乎对我有用。也许可以比较一下,看看您可能会采取哪些不同的做法?

const img = new Image();
img.addEventListener('load', render);
img.crossOrigin = "";
img.src = "https://i.imgur.com/ZKMnXce.png";

function render() {
const vs = `
attribute vec4 position;
void main() {
gl_PointSize = 80.0;
gl_Position = position;
}
`;

const fs = `
precision mediump float;
uniform sampler2D tex;
void main() {
gl_FragColor = texture2D(tex, gl_PointCoord);
}
`;

const gl = document.querySelector("canvas").getContext("webgl");
const program = twgl.createProgram(gl, [vs, fs]);
const positionLoc = gl.getAttribLocation(program, "position");

const ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = img.width;
ctx.canvas.height = img.height;
ctx.fillStyle = '#FFF'
ctx.drawImage(img, 0, 0);
ctx.font = "bold 48px sans-serif";
ctx.fillText("imageData", 10, 200);

const imgData = ctx.getImageData(0, 0, img.width, img.height);

ctx.drawImage(img, 0, 0);
ctx.fillText("canvas", 10, 200);

gl.useProgram(program);

createTextureAndDraw(img, -.6);
createTextureAndDraw(ctx.canvas, 0);
createTextureAndDraw(imgData, .6);

function createTextureAndDraw(src, x) {

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
{
const level = 0;
const internalFormat = gl.RGBA;
const width = 1;
const height = 1;
const border = 0;
const format = gl.RGBA;
const type = gl.UNSIGNED_BYTE;
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
format, type, src);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
}

gl.vertexAttrib1f(positionLoc, x);

const primitiveType = gl.POINTS;
const offset = 0;
const count = 1;
gl.drawArrays(primitiveType, offset, count);
}
}
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
<canvas></canvas>

阅读问题的更新后,您可能应该提出一个新问题,因为您的实际问题与您提出的问题根本无关。

首先,Canvas 是始终预先多重化的。这意味着它是有损的。

这个答案详细介绍了这一点:https://stackoverflow.com/a/50566789/128511

由于您要使用 Image(png) -> Canvas -> ImageData,那么如果您的 PNG 有任何非 255 alpha,您将丢失数据。

其次你提到了 Gamma 校正。是的,浏览器将对图像进行 Gamma 校正和/或应用其他颜色转换。这样,在 WebGL 中绘制的图像将与绘制到 Canvas 中的图像以及页面上显示的图像相匹配。

为了避免颜色转换,您需要设置 gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE) ,它告诉 WebGL 采取任何措施从图像中获取原始数据(可能包括从头开始重新解码图像,因为图像的默认数据是浏览器在 HTML 中绘制图像标签所需的任何格式。

这是一个不应用颜色转换的示例。它从同一图像创建 2 个纹理。一次使用默认颜色转换,一次不使用。

const img = new Image();
img.addEventListener('load', render);
img.crossOrigin = "";
img.src = "https://cdn.rawgit.com/KhronosGroup/WebGL/8ea92581/sdk/tests/resources/small-square-with-colorspin-profile.png";

function render() {
const vs = `
attribute vec4 position;
void main() {
gl_PointSize = 130.0;
gl_Position = position;
}
`;

const fs = `
precision mediump float;
uniform sampler2D tex;
void main() {
gl_FragColor = texture2D(tex, gl_PointCoord);
}
`;

const gl = document.querySelector("canvas").getContext("webgl");
const program = twgl.createProgram(gl, [vs, fs]);
const positionLoc = gl.getAttribLocation(program, "position");

gl.useProgram(program);

createTextureAndDraw(img, -.5, true); // default (with COLOR CONVERSION)
createTextureAndDraw(img, .5, false); // color conversion OFF

function createTextureAndDraw(src, x, colorConversion) {

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
const mode = colorConversion ? gl.BROWSER_DEFAULT_WEBGL : gl.NONE;
gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, mode);
{
const level = 0;
const internalFormat = gl.RGBA;
const width = 1;
const height = 1;
const border = 0;
const format = gl.RGBA;
const type = gl.UNSIGNED_BYTE;
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
format, type, src);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
}

gl.vertexAttrib1f(positionLoc, x);

const primitiveType = gl.POINTS;
const offset = 0;
const count = 1;
gl.drawArrays(primitiveType, offset, count);
}
}
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
<canvas></canvas>

注意:这是一个极端的例子,因为经过颜色转换后纹理为红色,未经颜色转换时纹理为蓝色。如果您在 Photoshop 中打开该文件,您会看到原始数据是蓝色的,但根据颜色配置文件,它显示为红色。

enter image description here

WebGL conformance test for this feature中有几个极端的例子测试您是否可以在 WebGL 中从 PNG 获取原始数据。

关于javascript - gl.texImage2D 适用于 Image,但不适用于 ImageData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50664018/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com