javascript - 如何使用 Three.js 在着色器中传递和使用查找表

标签 javascript three.js glsl

我编写了一个使用高度图的简单的 Three.js。这是创建着色器 Material 的相关代码:

function loadHeightMap() {
    // fake a lookup table
    var lut = [];
    for ( var n=0; n<256; n++ ) {
       lut.push(new THREE.Vector3(0.5, 0.4, 0.3));
    }

    var loader = new THREE.TextureLoader();
    var zScale = 10;

    var mapLoc = "https://s22.postimg.org/8n93ehmep/Terrain128.png";
    loader.load(mapLoc, function ( texture ) {
    // use "this." to create global object
    this.customUniforms = {
        zTexture:   { type: "t", value: texture },
        zScale:     { type: "f", value: zScale },
        zLut:       { type: "v3v", value: lut }
    };

    var customMaterial = new THREE.ShaderMaterial({
        uniforms: customUniforms,
        vertexShader:   document.getElementById( 'vertexShader'   ).textContent,
        fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
        side: THREE.DoubleSide
    });

    var planeGeo = new THREE.PlaneGeometry( 20, 20, 129, 129 );
    var plane = new THREE.Mesh( planeGeo, customMaterial );
    plane.rotation.x = -Math.PI / 2;
    plane.position.y = 0;

    scene.add(plane);
});
}

这是着色器:

<script id="vertexShader" type="x-shader/x-vertex">
    uniform sampler2D   zTexture;
    uniform float       zScale;
    uniform vec3        zLut[ 256 ];

    varying float vAmount;

    void main() {
      vec4 heightData = texture2D( zTexture, uv );

      vAmount = heightData.r; 

      // move the position along the normal
      vec3 newPosition = position + normal * zScale * vAmount;

       gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
   }
</script>

<script id="fragmentShader" type="x-shader/x-vertex">
    uniform vec3        zLut[ 256 ];

 varying float vAmount;

 void main() {
     int index = int(vAmount) * 255;
       vec3 vColor = vec3(vAmount, vAmount, vAmount);
       //gl_FragColor = vec4(zLut[index], 1.0);
       gl_FragColor = vec4(vColor, 1.0);
  }

着色器和高度图部分工作正常。但我想传递查找表(zLut)。如果我不尝试使用查找表,上面的代码可以正常工作。一个有效的示例是 here 。我也创建了一个 fiddle here但由于 CORS 问题而失败。

欢迎任何建议。

最佳答案

好的,解决了这个问题(大部分)。诀窍是在顶点着色器中获取查找颜色,其中可以索引到具有非常量值的数组。将生成的颜色作为变化的颜色传递给fragmentShader。所以这两个着色器最终是:

<script id="vertexShader" type="x-shader/x-vertex">
        uniform sampler2D   vTexture;
        uniform float       vScale;
        uniform vec3        vLut[ 256 ];

        varying vec3        vColor;

        void main() {

            vec4 heightData = texture2D( vTexture, uv );

            // assuming map is grayscale it doesn't matter if you use r, g, or b.
            float vAmount = heightData.r;

            // fetch the color from the lookup table so it gets passed to the fragshader
            int index = int(heightData.r * 255.0);
            vColor = vLut[index];

            // move the position along the normal
            vec3 newPosition = position + normal * vScale * vAmount;

            gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
        }
    </script>

    <script id="fragmentShader" type="x-shader/x-vertex">

        varying vec3  vColor;

        void main() {

            gl_FragColor = vec4(vColor, 1.0);
        }
    </script>

我剩下的问题是渲染时颜色都是平坦的。我尝试强制更新动画函数中的顶点,但没有成功。仍在研究,但这里的问题已经解决(AFAIK)。

可以看到结果here

关于javascript - 如何使用 Three.js 在着色器中传递和使用查找表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43595639/

相关文章:

OpenGL 着色器节点编辑器

javascript - jQuery 编码标准和最佳实践(分离事件和函数)

javascript - 复选框处于事件状态时重复功能

javascript - 加载 js 文件 - 将它们全部连接起来

javascript - 检查两个数组是否相等并禁用具有相同值的数组按钮

javascript - Three.js - 来自 Math.Plane 的 PlaneGeometry

javascript - 三个 JS 像素化渲染目标?

javascript - 如何在矩形上打洞(Three.js)?

opengl-es - OpenGL 着色器编译器可以优化制服上的表达式吗?

opengl - "GL_HALF_FLOAT"具有 OpenGL 渲染和 GLSL