javascriptthree.jsglslshadershadermaterial

GLSL shader not showing anything in scene in THREE.js - why?


I'm trying to make my own shader for a THREE.js project I'm working on, and I wanted to make a GLSL shader as part of it for one of the meshes in my scene. However, despite writing very basic code for it, the mesh (just a cylinder) won't display at all in the scene. This was the relevant code I've been working with at the moment:

main.js:

import * as THREE from 'three'

const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(
    80, /* FOV */
    window.innerWidth / window.innerHeight, /* aspect ratio */
    0.1, /* closest visible distance */
    1000 /* furthest visible distance */
)

camera.position.x = -0.15
camera.position.y = 0.15
camera.position.z = 0.15
camera.lookAt(new THREE.Vector3(0, 0, 0))

const renderer = new THREE.WebGLRenderer({
    antialias: true
})

renderer.setSize(
    window.innerWidth, /* width */
    window.innerHeight /* height */
)

document.body.appendChild(renderer.domElement)

let cylinderGeometry = new THREE.CylinderGeometry(0.002, 0.002, 0.25)

let cylinderMaterial = new THREE.ShaderMaterial({
    vertexShader: document.getElementById("vertexShader").textContent,
    fragmentShader: document.getElementById("fragmentShader").textContent
})

let cylinderMesh = new THREE.Mesh(cylinderGeometry, cylinderMaterial)
cylinderMesh.position.y = 0.125
scene.add(cylinderMesh)

function animate() {

    window.requestAnimationFrame(animate)
    renderer.render(scene, camera)
}

animate()

index.html:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Rubik's Cube</title>
        <style>
            body { margin: 0; }
        </style>
    </head>
    <body style="background-color: #dedede">
        <script type="module" src="./src/main.js"></script>
        <script id="vertexShader" type="x-shader/x-vertex"> 
            void main() {
                gl_Position = vec4(1.0, 1.0, 1.0, 1.0 );
            }
        </script>
        <script id="fragmentShader" type="x-shader/x-fragment">
            void main() {
                gl_FragColor = vec4(1.0, 1.0, 1.0 ,1.0);
            }
        </script>
    </body>
</html>

Apologies if the answer happened to be obvious – this is my first time working with GLSL.


Solution

  • You neet use vertex position coming from 3js and transform it with model-view-projection matrix. Now your every vertex is placed at clip-space coords 1,1,1,1 and all vertices are set into single point, so you see nothing. Try in vertex

    void main() {
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }