34

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

rrowland
  • 2,734
  • 2
  • 17
  • 32

1 Answers1

40

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" ) }
};
laike9m
  • 18,344
  • 20
  • 107
  • 140
Gero3
  • 2,817
  • 1
  • 22
  • 21
  • 1
    Wow, I feel so stupid. Thank you! This was the problem. It's hard to keep track of or even be aware of all relevant syntax changes with the limited documentation available and most examples running older revisions. – rrowland Sep 27 '12 at 20:01
  • 6
    That's normal. No need to bash your self. But this can be a big help when you ever need a update. https://github.com/mrdoob/three.js/wiki/Migration – Gero3 Sep 27 '12 at 20:34
  • 6
    Also, always use as reference the examples in the repo. These are always updated and working. – mrdoob Sep 27 '12 at 23:33
  • 1
    FYI the `loadTexture` util is deprecated in favor of the `TextureLoader` object which you can use like so: `var texture = new THREE.TextureLoader().load( 'textures/land_ocean_ice_cloud_2048.jpg' );` More info there: https://threejs.org/docs/#api/en/loaders/TextureLoader – paascal Sep 21 '19 at 11:01