Custom Texture Shader in Three.js

32,375

You are still using the old syntax for uniforms

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

This is the new syntax

var uniforms = {
    texture1: { type: "t", value: THREE.ImageUtils.loadTexture( "texture.jpg" ) }
};
Share:
32,375
rrowland
Author by

rrowland

Currently working as a Software Engineer at Twilio, working on the Real Time Communication SDKs for JavaScript. I specialize in full-stack Web Development, and lately I've been very interested in using a full JavaScript stack.

Updated on August 09, 2020

Comments

  • rrowland
    rrowland almost 4 years

    I'm just looking to create a very simple Fragment Shader that draws a specified texture to the mesh. I've looked at a handful of custom fragment shaders that accomplished the same and built my own shaders and supporting JS code around it. However, it's just not working. Here's a working abstraction of the code I'm trying to run:

    Vertex Shader

    <script id="vertexShader" type="x-shader/x-vertex">
        varying vec2 vUv;
    
        void main() {
            vUv = uv;
    
            gl_Position =   projectionMatrix * 
                            modelViewMatrix * 
                            vec4(position,1.0);
        }
    </script>
    

    Fragment Shader

    <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>
    

    Scene Code

    <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 exists, and displays when mapped to a MeshLambertMaterial. When switching my fragment shader to a simple color (Commented out in code) it properly displays the ball.

    Running this displays nothing at all. I don't get any errors, the ball just doesn't appear at all.

    I know I must be doing something fundamentally wrong, but I've been looking over the same examples in which this code seems to work for a couple days now and I feel like I'm bashing my head against a wall. Any help would be appreciated!

    Edit: I am using Three.js Revision 51