gpt4 book ai didi

three.js - 基于相机位置和纹理坐标的三点闪烁,但仅限于 Nvidia 卡

转载 作者:行者123 更新时间:2023-12-04 21:34:20 25 4
gpt4 key购买 nike

我有一个闪烁的 THREE.Points 问题,具体取决于它们的 UV 坐标,如以下代码笔所示:http://codepen.io/anon/pen/qrdQeY?editors=0010

codepen中的代码尽量精简(171行),
但总结一下我在做什么:

  • 使用 THREE.Points
  • 渲染 Sprite
  • BufferGeometry 包含每个 Sprite 的 Sprite 表索引和位置
  • 带有自定义顶点和像素着色器的 RawShaderMaterial 用于查找给定索引的 Sprite 的 UV 坐标
  • 具有 4x4 单元格的 128x128px Sprite 表包含 Sprite

  • 这是代码:
    /// FRAGMENT SHADER ===========================================================
    const fragmentShader = `
    precision highp float;

    uniform sampler2D spritesheet;

    // number of spritesheet subdivisions both vertically and horizontally
    // e.g. for a 4x4 spritesheet this number is 4
    uniform float spritesheetSubdivisions;

    // vParams[i].x = sprite index
    // vParams[i].z = sprite alpha
    varying vec3 vParams;

    /**
    * Maps regular UV coordinates spanning the entire spritesheet
    * to a specific sprite within the spritesheet based on the given index,
    * which points into a spritesheel cell (depending on spritesheetSubdivisions
    * and assuming that the spritesheet is regular and square).
    */
    vec2 spriteIndexToUV(float idx, vec2 uv) {
    float cols = spritesheetSubdivisions;
    float rows = spritesheetSubdivisions;

    float x = mod(idx, cols);
    float y = floor(idx / cols);

    return vec2(x / cols + uv.x / cols, 1.0 - (y / rows + (uv.y) / rows));
    }

    void main() {
    vec2 uv = spriteIndexToUV(vParams.x, gl_PointCoord);
    vec4 diffuse = texture2D(spritesheet, uv);

    float alpha = diffuse.a * vParams.z;
    if (alpha < 0.5) discard;

    gl_FragColor = vec4(diffuse.xyz, alpha);
    }
    `

    // VERTEX SHADER ==============================================================
    const vertexShader = `
    precision highp float;

    uniform mat4 modelViewMatrix;
    uniform mat4 projectionMatrix;
    uniform float size;
    uniform float scale;

    attribute vec3 position;
    attribute vec3 params; // x = sprite index, y = unused, z = sprite alpha
    attribute vec3 color;

    varying vec3 vParams;

    void main() {
    vParams = params;

    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
    gl_Position = projectionMatrix * mvPosition;
    gl_PointSize = size * ( scale / - mvPosition.z );
    }
    `

    // THREEJS CODE ===============================================================

    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

    const renderer = new THREE.WebGLRenderer({canvas: document.querySelector("#mycanvas")});
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setClearColor(0xf0f0f0)

    const pointGeometry = new THREE.BufferGeometry()
    pointGeometry.addAttribute("position", new THREE.BufferAttribute(new Float32Array([
    -1.5, -1.5, 0,
    -0.5, -1.5, 0,
    0.5, -1.5, 0,
    1.5, -1.5, 0,

    -1.5, -0.5, 0,
    -0.5, -0.5, 0,
    0.5, -0.5, 0,
    1.5, -0.5, 0,

    -1.5, 0.5, 0,
    -0.5, 0.5, 0,
    0.5, 0.5, 0,
    1.5, 0.5, 0,

    -1.5, 1.5, 0,
    -0.5, 1.5, 0,
    0.5, 1.5, 0,
    1.5, 1.5, 0,
    ]), 3))

    pointGeometry.addAttribute("params", new THREE.BufferAttribute(new Float32Array([
    0, 0, 1, // sprite index 0 (row 0, column 0)
    1, 0, 1, // sprite index 1 (row 0, column 1)
    2, 0, 1, // sprite index 2 (row 0, column 2)
    3, 0, 1, // sprite index 3 (row 0, column 4)

    4, 0, 1, // sprite index 4 (row 1, column 0)
    5, 0, 1, // sprite index 5 (row 1, column 1)
    6, 0, 1, // ...
    7, 0, 1,

    8, 0, 1,
    9, 0, 1,
    10, 0, 1,
    11, 0, 1,

    12, 0, 1,
    13, 0, 1,
    14, 0, 1,
    15, 0, 1
    ]), 3))

    const img = document.querySelector("img")
    const texture = new THREE.TextureLoader().load(img.src);

    const pointMaterial = new THREE.RawShaderMaterial({
    transparent: true,
    vertexShader: vertexShader,
    fragmentShader: fragmentShader,
    uniforms: {
    spritesheet: {
    type: "t",
    value: texture
    },
    spritesheetSubdivisions: {
    type: "f",
    value: 4
    },
    size: {
    type: "f",
    value: 1
    },
    scale: {
    type: "f",
    value: window.innerHeight / 2
    }
    }
    })

    const points = new THREE.Points(pointGeometry, pointMaterial)
    scene.add(points)

    const render = function (timestamp) {
    requestAnimationFrame(render);


    camera.position.z = 5 + Math.sin(timestamp / 1000.0)

    renderer.render(scene, camera);
    };

    render();

    // resize viewport
    window.addEventListener( 'resize', onWindowResize, false );

    function onWindowResize(){

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );

    }

    如果你有 Nvidia 卡,你会看到三个 Sprite 在相机闪烁时
    沿 Z 轴来回移动。在集成的英特尔图形芯片上
    问题不会发生。

    我不知道如何解决这个问题。受影响的 uv 坐标看起来有点随机。我将不胜感激任何指点。

    最佳答案

    spriteIndexToUV() 函数中的 mod()/floor() 计算在某些星座中引起问题(当 spriteindex 是 spritesheetSubdivisions 的倍数时)。

    我可以通过用一个小 epsilon 调整 cols 变量来修复它:

    vec2 spriteIndexToUV(float idx, vec2 uv) 
    {
    float cols = spritesheetSubdivisions - 1e-6; // subtract epsilon
    float rows = spritesheetSubdivisions;

    float x = mod(idx, cols);
    float y = floor(idx / cols);

    return vec2(x / cols + uv.x / cols, 1.0 - (y / rows + (uv.y) / rows));
    }

    PS:那个codepen的东西真的很酷,不知道它存在:-)

    编辑:这样写可能更好/更清晰:
    float cols = spritesheetSubdivisions;
    float rows = spritesheetSubdivisions;

    float y = floor ((idx+0.5) / cols);
    float x = idx - cols * y;

    这样,我们就可以完全清除地板操作中的任何危急情况——而且我们摆脱了 mod() 调用。

    至于为什么 floor (idx/4)idx 时,有时会产生 0 而不是 1应该正好是4.0,我只能推测 varying vec3 vParams当它从顶点着色器进入片段着色器阶段时会受到一些插值,从而导致片段着色器看到例如3.999999 而不是 4.0。

    关于three.js - 基于相机位置和纹理坐标的三点闪烁,但仅限于 Nvidia 卡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42327736/

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