Three.js 中的自定义纹理着色器

Posted

技术标签:

【中文标题】Three.js 中的自定义纹理着色器【英文标题】:Custom Texture Shader in Three.js 【发布时间】:2012-09-19 14:17:40 【问题描述】:

我只是想创建一个非常简单的片段着色器,它可以将指定的纹理绘制到网格。我查看了一些实现相同功能的自定义片段着色器,并构建了我自己的着色器并支持围绕它的 JS 代码。但是,它只是行不通。这是我尝试运行的代码的工作抽象:

顶点着色器

<script id="vertexShader" type="x-shader/x-vertex">
    varying vec2 vUv;

    void main() 
        vUv = uv;

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

片段着色器

<script id="fragmentShader" type="x-shader/x-fragment">
    uniform sampler2D texture1;

    varying vec2 vUv;

    void main() 
        gl_FragColor = texture2D(texture1, vUv); // Displays Nothing
        //gl_FragColor = vec4(0.5, 0.2, 1.0, 1.0); // Works; Displays Flat Color
    
</script>

场景代码

<script>
    // Initialize WebGL Renderer
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    var canvas = document.getElementById('canvas').appendChild(renderer.domElement);

    // Initialize Scenes
    var scene = new THREE.Scene();

    // Initialize Camera
    var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 100);
    camera.position.z = 10;

    // Create Light
    var light = new THREE.PointLight(0xFFFFFF);
    light.position.set(0, 0, 500);
    scene.add(light);

    // Create Ball
    var vertShader = document.getElementById('vertexShader').innerhtml;
    var fragShader = document.getElementById('fragmentShader').innerHTML;

    var uniforms = 
        texture1:  type: 't', value: 0, texture: THREE.ImageUtils.loadTexture( 'texture.jpg' ) 
    ;

    var material = new THREE.ShaderMaterial(
        uniforms: uniforms,
        vertexShader: vertShader,
        fragmentShader: fragShader
    );

    var ball = new THREE.Mesh(new THREE.SphereGeometry(1, 50, 50), material);
    scene.add(ball);

    // Render the Scene
    renderer.render(scene, camera);
</script>

texture.jpg 存在,并在映射到 MeshLambertMaterial 时显示。将我的片段着色器切换为简单的颜色(在代码中注释掉)时,它会正确显示球。

运行它什么都不会显示。我没有收到任何错误,球根本没有出现。

我知道我一定是在做一些根本性的错误,但我一直在查看相同的示例,在这些示例中,这段代码似乎已经运行了几天,我觉得我的头撞到了墙上。任何帮助将不胜感激!

编辑:我正在使用 Three.js 修订版 51

【问题讨论】:

你用的是什么版本的three.js?? 【参考方案1】:

你仍在使用制服的旧语法

var uniforms = 
    texture1: 
        type: "t",
        value: 0,
        texture: THREE.ImageUtils.loadTexture("texture.jpg")
    
;

这是新语法

var uniforms = 
    texture1:  type: "t", value: THREE.ImageUtils.loadTexture( "texture.jpg" ) 
;

【讨论】:

哇,我觉得自己好蠢。谢谢!这就是问题所在。由于可用的文档有限且大多数示例都运行旧版本,因此很难跟踪甚至了解所有相关的语法更改。 这很正常。没必要打自己。但是,当您需要更新时,这可能是一个很大的帮助。 github.com/mrdoob/three.js/wiki/Migration 另外,请始终将 repo 中的示例用作参考。这些总是更新和工作。 仅供参考,loadTexture 实用程序已被弃用,取而代之的是 TextureLoader 对象,您可以像这样使用:var texture = new THREE.TextureLoader().load( 'textures/land_ocean_ice_cloud_2048.jpg' ); 更多信息:threejs.org/docs/#api/en/loaders/TextureLoader

以上是关于Three.js 中的自定义纹理着色器的主要内容,如果未能解决你的问题,请参考以下文章

使用 ShaderMaterial 复制 MeshLambertMaterial 会忽略纹理

如何将 Three.js 着色器应用于节点

three.js 着色器材质基础

three.js 着色器材质之变量

使用shader着色器程序创建扩散光圈效果(three.js实战10)

是否有可能消除three.js着色器中的引号和逗号的麻烦?