gpt4 book ai didi

javascript - 无法在 webgl 中将 Canvas 渲染为纹理,但可以渲染蓝色

转载 作者:行者123 更新时间:2023-11-28 03:37:10 24 4
gpt4 key购买 nike

我正在尝试将 Canvas 渲染为 webgl 中的纹理。

这是代码:

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture);
// gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([0, 0, 255, 255]));

第一行,texture是一个canvas dom元素,它填充有红色,如果我将它附加到document.body它渲染得很好。但这一行不会在 webgl 上渲染任何内容。

如果我取消注释第二行,它会呈现蓝色就好。

const fShaderSource = `#version 300 es

precision mediump float;

out vec4 outColor;

uniform sampler2D u_texture;

void main() {
outColor = texture(u_texture, vec2(0.0));
}

`;

const vShaderSource = `#version 300 es

precision mediump float;

in vec2 a_position;

void main() {
gl_Position = vec4(a_position, 0, 1);
}
`;

main(document.getElementById('app'));

function main(element) {

const canvas = document.createElement('canvas'),
gl = canvas.getContext('webgl2');
element.append(canvas);
const displayWidth = canvas.clientWidth,
displayHeight = canvas.clientHeight;
canvas.width = displayWidth;
canvas.height = displayHeight;


let graphics = new Graphics({width: displayWidth, height: displayHeight}, gl);

new Loop(() => {
graphics.render();
}).start();
}

function Graphics(state, gl) {

const { width, height } = state;

let vShader = createShader(gl, gl.VERTEX_SHADER, vShaderSource);
let fShader = createShader(gl, gl.FRAGMENT_SHADER, fShaderSource);

let program = createProgram(gl, vShader, fShader);

let posAttrLocation = gl.getAttribLocation(program, "a_position");
let posBuffer = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);


/*
(-1, 1).( 1, 1)
.
(-1,-1).( 1,-1)
*/
let positions = [
-1, 1,
-1, -1,
1, -1,
-1, 1,
1,-1,
1, 1
];

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);


let vao = gl.createVertexArray();
gl.bindVertexArray(vao);

gl.enableVertexAttribArray(posAttrLocation);

let size = 2,
type = gl.FLOAT,
normalize = false,
stride = 0,
offset = 0;

gl.vertexAttribPointer(posAttrLocation,
size,
type,
normalize,
stride,
offset);

let glTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, glTexture);

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvasTexture());
//gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 255, 255]));




let resUniformLocation = gl.getUniformLocation(program, "u_resolution");

let texUniformLocation = gl.getUniformLocation(program, "u_texture");




gl.clearColor(0, 0, 0, 0);

this.render = () => {
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT);

gl.useProgram(program);

gl.uniform2f(resUniformLocation, gl.canvas.width, gl.canvas.height);

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, glTexture);

gl.bindVertexArray(vao);
gl.drawArrays(gl.TRIANGLES, 0, 6);


};

}

function canvasTexture() {

return withCanvasTexture(256, 256, (w, h, canvas, ctx) => {
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, w, h);
ctx.font = '50pt Comic Sans';
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('label', w / 2, 50);

return canvas;
});

function withCanvasTexture(width, height, f) {
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
f(width, height, canvas, canvas.getContext('2d'));
const texture = canvas;
document.body.append(canvas);
return texture;
}
}

function createShader(gl, type, source) {
let shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);

if (success) {
return shader;
}

console.error(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
};

function createProgram(gl, vShader, fShader) {
let program = gl.createProgram();
gl.attachShader(program, vShader);
gl.attachShader(program, fShader);
gl.linkProgram(program);
let success = gl.getProgramParameter(program, gl.LINK_STATUS);
if (success) {
return program;
}

console.error(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
return null;
}


// Loop Library
function Loop(fn) {

const perf = window.performance !== undefined ? window.performance : Date;

const now = () => perf.now();

const raf = window.requestAnimationFrame;

let running = false,
lastUpdate = now(),
frame = 0;

this.start = () => {
if (running) {
return this;
}

running = true;
lastUpdate = now();
frame = raf(tick);
return this;
};

this.stop = () => {
running = false;

if (frame != 0) {
raf.cancel(frame);
}

frame = 0;
return this;
};

const tick = () => {
frame = raf(tick);
const time = now();
const dt = time - lastUpdate;
fn(dt);
lastUpdate = time;
};
}
#app canvas {
position: fixed;
top: 50%;
bottom: 0;
left: 50%;
right: 0;

width: 100vmin;
height: 70vmin;

transform: translate(-50%, -25%);

image-rendering: optimizeSpeed;
cursor: none;
margin: auto;
}
<div id="app">
</div>

最佳答案

您没有正确设置过滤。

要渲染没有 mips 的纹理,您必须将最小过滤器设置为 LINEAR 或 NEAREST,因为这些模式不尝试使用 mips

 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

要么你需要提供 mips

 gl.generateMipmap(gl.TEXTURE_2D);

关于javascript - 无法在 webgl 中将 Canvas 渲染为纹理,但可以渲染蓝色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57605966/

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