Search code examples
javascriptthree.jsglslshader

My THREE.js RawShaderMaterial isn't Working


I have had no problems loading others' shaders into THREE.js, but I seem to have run into a problem creating and running my own. The shader works on the site I used to create it (https://shaderfrog.com/app/view/5460), but not when I tried to implement it. I am not sure whether it is a javascript, three.js or GLSL problem, so all help would be greatly appreciated.

Here is my js code:

function newCube(colour=0xffffff,height=1,width=height,depth=height){
  const geometry = new THREE.CubeGeometry(height,depth,width);
  const material = new THREE.MeshBasicMaterial( {color: colour} );
  return(new THREE.Mesh( geometry, material ));
}
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60,window.innerWidth / window.innerHeight,1,10000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xaaaaaa, 1);
document.body.appendChild(renderer.domElement);
const cube = newCube(0x220033,1);
var material= new THREE.RawShaderMaterial({
  "id": 5472,
  "name": "Fragmented",
  "fragmentShader": "precision highp float;\nprecision highp int;\n\nuniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nuniform float time;\nuniform vec3 color;\nuniform vec3 lightPosition;\nvarying vec3 vPosition;\nvarying vec3 vNormal;\nvarying vec3 vColor;\nvarying vec2 vUv;\nvarying vec2 vUv2;\n\nvoid main() {\n    vec3 worldPosition = ( modelMatrix * vec4( vPosition, 1.0 )).xyz;\n    vec3 worldNormal = normalize( vec3( modelMatrix * vec4( vNormal, 0.0 ) ) );\n    vec3 lightVector = normalize( lightPosition - worldPosition );\n    float brightness = dot( worldNormal, lightVector );\n    gl_FragColor = vec4( color * brightness, 1.0 );\n}",
  "vertexShader": "precision highp float;\nprecision highp int;\nuniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nuniform float time;\nuniform vec3 color;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\nvarying vec3 vPosition;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nvarying vec2 vUv2;\nvoid main() {\n    vNormal = normal;\n    vUv = uv;\n    vUv2 = uv2;\n    vPosition = position;\n    gl_Position= projectionMatrix * modelViewMatrix * vec4( position+sin(position*time)/10., 1. );\n}",
  "uniforms": {
    "time": {
      "name": "time",
      "displayName": null,
      "type": "f",
      "glslType": "float",
      "useGridHelper": false,
      "useRange": false,
      "range": null,
      "isRandom": false,
      "randomRange": null,
      "useToggle": false,
      "toggle": null,
      "description": "",
      "value":0
    },
    "color": {
      "name": "color",
      "displayName": null,
      "type": "c",
      "glslType": "vec3",
      "useGridHelper": false,
      "useRange": false,
      "range": null,
      "isRandom": false,
      "randomRange": null,
      "useToggle": false,
      "toggle": null,
      "description": "Example light color"
    },
    "lightPosition": {
      "name": "lightPosition",
      "displayName": null,
      "type": "v3",
      "glslType": "vec3",
      "useGridHelper": false,
      "useRange": false,
      "range": null,
      "isRandom": false,
      "randomRange": null,
      "useToggle": false,
      "toggle": null,
      "description": ""
    }
  }
});
scene.add(cube);
cube.material=material;
camera.position.z = 3;

function render() {
  cube.material.uniforms.time.value+=0.1;
  renderer.render(scene, camera);
  cube.mesh.rotation.x += 0.05;
  cube.mesh.rotation.y -= 0.05;
  requestAnimationFrame(render);
}

render();

Solution

  • I modified your code, so at least it shows something:

    body{
      overflow: hidden;
      margin: 0;
    }
    <script type="module">
    import * as THREE from "https://cdn.skypack.dev/[email protected]";
    
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(60,window.innerWidth / window.innerHeight,1,10000);
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setClearColor(0xaaaaaa, 1);
    document.body.appendChild(renderer.domElement);
    var geometry = new THREE.BoxGeometry();
    var material= new THREE.RawShaderMaterial({
      "fragmentShader": "precision highp float;\nprecision highp int;\n\nuniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nuniform float time;\nuniform vec3 color;\nuniform vec3 lightPosition;\nvarying vec3 vPosition;\nvarying vec3 vNormal;\nvarying vec3 vColor;\nvarying vec2 vUv;\nvarying vec2 vUv2;\n\nvoid main() {\n    vec3 worldPosition = ( modelMatrix * vec4( vPosition, 1.0 )).xyz;\n    vec3 worldNormal = normalize( vec3( modelMatrix * vec4( vNormal, 0.0 ) ) );\n    vec3 lightVector = normalize( lightPosition - worldPosition );\n    float brightness = dot( worldNormal, lightVector );\n    gl_FragColor = vec4( color * brightness, 1.0 );\n}",
      "vertexShader": "precision highp float;\nprecision highp int;\nuniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nuniform float time;\nuniform vec3 color;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\nvarying vec3 vPosition;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nvarying vec2 vUv2;\nvoid main() {\n    vNormal = normal;\n    vUv = uv;\n    vUv2 = uv2;\n    vPosition = position;\n    gl_Position= projectionMatrix * modelViewMatrix * vec4( position+sin(position*time)/10., 1. );\n}",
      "uniforms": {
        "time": {
          "value":0
        },
        "color": {
          "value": new THREE.Color(0x320064)
        },
        "lightPosition": {
          "value": new THREE.Vector3().setScalar(5)
        }
      }
    });
    var cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    camera.position.z = 3;
    
    function render() {
      cube.material.uniforms.time.value+=0.1;
      renderer.render(scene, camera);
      cube.rotation.x += 0.01;
      cube.rotation.y -= 0.01;
      requestAnimationFrame(render);
    }
    
    render();
    </script>