gpt4 book ai didi

glsl - 为什么每次在 p5js 中调用 glsl 着色器时,纹理坐标都会反转?

转载 作者:行者123 更新时间:2023-12-04 07:39:18 25 4
gpt4 key购买 nike

我正在尝试使用带有 p5js 的 glsl 着色器来创建类似生命游戏的模拟。为此,我想创建一个着色器,该着色器将采用统一的纹理,并根据之前的纹理绘制新纹理。在下一次迭代中,这个新纹理将用作统一纹理,这应该允许我按照公开的想法创建模拟 here .我对 p5.js 很有经验,但我对着色器编程完全陌生,所以我可能遗漏了一些东西。
现在我的代码尽可能简单:

  • preload()函数,我使用 createImage() 创建纹理函数并将一些像素设置为白色,其他像素为黑色。
  • setup()函数我第一次使用这个纹理来运行着色器来创建一个新的纹理。我还设置了一个计时器来定期运行着色器并将结果绘制在缓冲区中。
  • draw()函数我在 Canvas 中绘制缓冲区。
  • 为了简单起见,我保持 Canvas 和纹理的大小相同。

  • 我的问题是,在某些时候 y我的代码中的坐标似乎倒置了,我不明白为什么。 我的理解是我的代码应该显示静止图像,但每次运行着色器时,图像都会反转。这就是我的意思:
    enter image description here
    我不确定我的问题是否来自我如何使用 glsl 或我如何使用 p5 或两者的混合。有人可以向我解释这个奇怪的地方 y反转从何而来?
    这是我的最小可重现示例(也在 p5 编辑器 here 中):
    草图文件:
    const sketch = (p5) => {
    const D = 100;
    let initialTexture;

    p5.preload = () => {
    // Create the initial image
    initialTexture = p5.createImage(D, D);
    initialTexture.loadPixels();
    for (let i = 0; i < initialTexture.width; i++) {
    for (let j = 0; j < initialTexture.height; j++) {
    const alive = i === j || i === 10 || j === 40;
    const color = p5.color(250, 250, 250, alive ? 250 : 0);
    initialTexture.set(i, j, color);
    }
    }
    initialTexture.updatePixels();

    // Initialize the shader
    shader = p5.loadShader('uniform.vert', 'test.frag');
    };

    p5.setup = () => {
    const canvas = p5.createCanvas(D, D, p5.WEBGL);
    canvas.parent('canvasDiv');

    // Create the buffer the shader will draw on
    graphics = p5.createGraphics(D, D, p5.WEBGL);
    graphics.shader(shader);

    /*
    * Initial step to setup the initial texture
    */
    // Used to normalize the frag coordinates
    shader.setUniform('u_resolution', [p5.width, p5.height]);
    // First state of the simulation
    shader.setUniform('u_texture', initialTexture);
    graphics.rect(0, 0, p5.width, p5.height);

    // Call the shader each time interval
    setInterval(updateSimulation, 1009);
    };

    const updateSimulation = () => {
    // Use the previous state as a texture
    shader.setUniform('u_texture', graphics);
    graphics.rect(0, 0, p5.width, p5.height);
    };

    p5.draw = () => {
    p5.background(0);
    // Use the buffer on the canvas
    p5.image(graphics, -p5.width / 2, -p5.height / 2);
    };
    };

    new p5(sketch);
    片段着色器现在只采用纹理的颜色并重用它(我尝试使用 st 而不是 uv 无济于事):
    precision highp float;

    uniform vec2 u_resolution;
    uniform sampler2D u_texture;

    // grab texcoords from vert shader
    varying vec2 vTexCoord;

    void main() {
    // Normalize the position between 0 and 1
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    // Get the texture coordinate from the vertex shader
    vec2 uv = vTexCoord;
    // Get the color at the texture coordinate
    vec4 c = texture2D(u_texture, uv);
    // Reuse the same color
    gl_FragColor = c;
    }
    还有我取自 an example 的顶点着色器除了传递坐标外,什么都不做:
    /*
    * vert file and comments from adam ferriss https://github.com/aferriss/p5jsShaderExamples with additional comments from Louise Lessel
    */

    precision highp float;

    // This “vec3 aPosition” is a built in shader functionality. You must keep that naming.
    // It automatically gets the position of every vertex on your canvas
    attribute vec3 aPosition;
    attribute vec2 aTexCoord;

    varying vec2 vTexCoord;

    // We always must do at least one thing in the vertex shader:
    // tell the pixel where on the screen it lives:

    void main() {
    // copy the texcoords
    vTexCoord = aTexCoord;

    // copy the position data into a vec4, using 1.0 as the w component
    vec4 positionVec4 = vec4(aPosition, 1.0);
    positionVec4.xy = positionVec4.xy * 2.0 - 1.0;

    // Send the vertex information on to the fragment shader
    // this is done automatically, as long as you put it into the built in shader function “gl_Position”
    gl_Position = positionVec4;
    }

    最佳答案

    长话短说:用 p5.js 绘制的矩形或平面的纹理坐标是左下角的 (0, 0) 和右上角的 (1, 1),其中作为从纹理是左上角的 (0, 0) 和右下角的 (1, 1)。您可以通过在片段着色器中注释掉颜色采样代码并使用以下内容来验证这一点:

    float val = (uv.x + uv.y) / 2.0;
    gl_FragColor = vec4(val, val, val, 1.0);
    正如您在生成的图像中看到的:
    enter image description here
    (0 + 0) / 2结果左下角为黑色, (1 + 1) / 2结果在右上角是白色的。
    因此,要对纹理的正确部分进行采样,您只需翻转 y uv 的组件向量:
    texture2D(u_texture, vec2(uv.x, 1.0 - uv.y));

    const sketch = (p5) => {
    const D = 200;
    let initialTexture;

    p5.preload = () => {
    // This doesn't actually need to go in preload
    // Create the initial image
    initialTexture = p5.createImage(D, D);
    initialTexture.loadPixels();
    for (let i = 0; i < initialTexture.width; i++) {
    for (let j = 0; j < initialTexture.height; j++) {
    // draw a big checkerboard
    const alive = (p5.round(i / 10) + p5.round(j / 10)) % 2 == 0;

    const color = alive ? p5.color('white') : p5.color(150, p5.map(j, 0, D, 50, 200), p5.map(i, 0, D, 50, 200));
    initialTexture.set(i, j, color);
    }
    }
    initialTexture.updatePixels();
    };

    p5.setup = () => {
    const canvas = p5.createCanvas(D, D, p5.WEBGL);

    // Create the buffer the shader will draw on
    graphics = p5.createGraphics(D, D, p5.WEBGL);
    // Initialize the shader
    shader = graphics.createShader(vert, frag);

    graphics.shader(shader);

    /*
    * Initial step to setup the initial texture
    */
    // Used to normalize the frag coordinates
    shader.setUniform('u_resolution', [p5.width, p5.height]);
    // First state of the simulation
    shader.setUniform('u_texture', initialTexture);
    graphics.rect(0, 0, p5.width, p5.height);

    // Call the shader each time interval
    setInterval(updateSimulation, 100);
    };

    const updateSimulation = () => {
    // Use the previous state as a texture
    shader.setUniform('u_texture', graphics);
    graphics.rect(0, 0, p5.width, p5.height);
    };

    p5.draw = () => {
    p5.background(0);
    // Use the buffer on the canvas
    p5.texture(graphics);
    p5.rect(-p5.width / 2, -p5.height / 2, p5.width, p5.height);
    };

    const frag = `
    precision highp float;

    uniform vec2 u_resolution;
    uniform sampler2D u_texture;

    // grab texcoords from vert shader
    varying vec2 vTexCoord;
    varying vec2 vPos;

    void main() {
    // Get the texture coordinate from the vertex shader
    vec2 uv = vTexCoord;

    gl_FragColor = texture2D(u_texture, vec2(uv.x, 1.0 - uv.y));

    //// For debugging uv coordinate orientation
    // float val = (uv.x + uv.y) / 2.0;
    // gl_FragColor = vec4(val, val, val, 1.0);
    }
    `;

    const vert = `
    /*
    * vert file and comments from adam ferriss https://github.com/aferriss/p5jsShaderExamples with additional comments from Louise Lessel
    */

    precision highp float;

    // This “vec3 aPosition” is a built in shader functionality. You must keep that naming.
    // It automatically gets the position of every vertex on your canvas
    attribute vec3 aPosition;
    attribute vec2 aTexCoord;

    varying vec2 vTexCoord;

    // We always must do at least one thing in the vertex shader:
    // tell the pixel where on the screen it lives:

    void main() {
    // copy the texcoords
    vTexCoord = aTexCoord;

    // copy the position data into a vec4, using 1.0 as the w component
    vec4 positionVec4 = vec4(aPosition, 1.0);
    // This maps positions 0..1 to -1..1
    positionVec4.xy = positionVec4.xy * 2.0 - 1.0;

    // Send the vertex information on to the fragment shader
    // this is done automatically, as long as you put it into the built in shader function “gl_Position”
    gl_Position = positionVec4;
    }`;
    };

    new p5(sketch);
    <script src="https://cdn.jsdelivr.net/npm/p5@1.3.1/lib/p5.js"></script>

    关于glsl - 为什么每次在 p5js 中调用 glsl 着色器时,纹理坐标都会反转?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67576655/

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