<div id="render" style="width:100%; height: 100%"></div>    
/**

Many thanks to prisoner849 for solving the algorithm for the gradient

@link https://discourse.threejs.org/t/gradient-to-textgeometry/1603/8

**/
// Requisiti: scene, camera e renderer
// scene è lo spazio
var scene = new THREE.Scene();

// (FOV verticale in degrees (default 50), aspect ratio, near, far)
// "near" e "far" servono per capire cosa renderizzare. In sostanza: 1000 è come un orizzonte
// 0.1 è la posizione dei "propri occhi", quindi se più vicino di 0.1 o lontano di 1000 nello spazio non si vede
var camera = new THREE.PerspectiveCamera(30, window.innerWidth/window.innerHeight, 0.1, 1000);
// qui si stabilisce la distanza della camera. Default è x 0, y 0, z 0
camera.lookAt(scene.position);
camera.position.set( 0, 20, 0 );

// WebGL render principale, ma si possono settare dei fallback
var renderer = new THREE.WebGLRenderer({ antialias: true })
// Si settano dimensioni finestra (più piccolo più performante), e opzionale 3° argomento a setSize "false" che permette di dimezzare la risoluzione (ancora più performante)
renderer.setSize( window.innerWidth, window.innerHeight, false );
// si colora lo sfondo di bianco
renderer.setClearColor(0xffffff, 1);
document.getElementById('render').appendChild( renderer.domElement );

// modulo dei controlli per il mouse di Three.js
var controls = new THREE.OrbitControls( camera, document.getElementsByClassName('wrapper')[0] );
// auto rotazione della camera e sua velocità, autorotatespeed default 2
controls.autoRotate = true;
controls.autoRotateSpeed = 0.1;
// velocità di rotazione all'input manuale 
controls.rotateSpeed = 0.1;
// effetto ease\inertia alla rotazione manuale, dampingFactor di default 0.25
controls.enableDamping = true;
controls.dampingFactor = 0.1;
// così si disabilita lo spostamento su x e y della camera
controls.enablePan = false;
// disabilitare zoom 
controls.enableZoom = false;
// abilitare rotazione, anche per singolo asse con valori da -Math.PI a Math.PI per i min e max
controls.minPolarAngle = Math.PI/2;
controls.maxPolarAngle = Math.PI/2;
//controls.update() must be called after any manual changes to the camera's transform
controls.update();

// luminosità d'ambiente. Alternativa è spotlight che è un punto di luce
// var ambientLight = new THREE.AmbientLight(0xeeeeee);
// scene.add(ambientLight);

// Per creare un oggetto, bisogna creare  degli oggetti 3d tendenzialmente chiamati "-prefisso"Geometry, cioè la forma
// ogni oggetto 3d a sua volta dev'essere costituito da un materiale a cui si applicheranno le palette di colori di tipo Mesh*Material, che quindi è l'aspetto
// Questi due servono a creare una Mesh, cioè Shape+Appearance che verrà aggiunto alla "scene"
// in questo caso ci serve un TextGeometry di una C usando un font, partendo da un font-family in formato json compatibile con three.js
// e grazie al FontLoader trasformarlo in un oggetto Shape usabile da three.js
var loader = new THREE.FontLoader();
loader.load('https://threejs.org/examples/fonts/helvetiker_bold.typeface.json', function (font) {
    // siccome bisogna aspettare che finisca la generazione del font prima di fare la scritta, si invoca la creazione
    // del testo in 3d in una funzione qua definita
    createText(font);
});
var text;
var geometry;
function createText(font) {
    container = document.createElement( 'div' );
    document.body.appendChild( container );
    // "forma" testo C
    geometry = new THREE.TextGeometry( "C", {
        font: font,
        size: 9,
        height: 3,
        curveSegments: 15,
        bevelEnabled: false
    });

    // calcola il cubo circoscritto, e si usano le dimensioni per centrare l'asse in mezzo alla "scene"
    geometry.computeBoundingBox();

    // serve a centrare l'oggetto in base all'asse centrale e non quello y
    geometry.center();

    var centerOffset = -0.5 * ( geometry.boundingBox.max.x - geometry.boundingBox.min.x );
    
    // due materiali: uno per l'interno e l'altro per l'esterno
    var materials = [
        new THREE.MeshBasicMaterial( { color: '#ECECEE'} ),
        new THREE.MeshBasicMaterial( { vertexColors: THREE.VertexColors, wireframe: false } )
    ];
    
    var faceIndices = [ 'a', 'b', 'c'];

    var bbox = geometry.boundingBox;
    var size = new THREE.Vector3().subVectors(bbox.max, bbox.min);
    var length = geometry.faces.length;
    var face, vertex, normalized = new THREE.Vector3(), normalizedAxis = 0;

    var colors = [{
        stop: 0,
        color: new THREE.Color(0xf7b000)
    }, {
        stop: .3,
        color: new THREE.Color(0xdd0080)
    }, {
        stop: .6,
        color: new THREE.Color(0x622b85)
    }, {
        stop: .85,
        color: new THREE.Color(0x007dae)
    }, {
        stop: 1,
        color: new THREE.Color(0x77c8db)
    }];
    var vertexIndices = ['a', 'b', 'c'];
    var axis = 'y', reverse = true;

    for (var c = 0; c < colors.length -1; c++) {

        var colorDiff = colors[c + 1].stop - colors[c].stop;

        for ( var i = 0; i < length; i++ ) 
        {
            face = geometry.faces[i];

            for (var v = 0; v < 3; v++){
                vertex = geometry.vertices[face[vertexIndices[v]]];
                normalizedAxis = normalized.subVectors(vertex, bbox.min).divide(size)[axis];
                if (reverse) {
                    normalizedAxis = 1 - normalizedAxis;
                }
                if (normalizedAxis >= colors[c].stop && normalizedAxis <= colors[c + 1].stop) {
                    var localNormalizedAxis = (normalizedAxis - colors[c].stop) / colorDiff;
                    face.vertexColors[v] = colors[c].color.clone().lerp(colors[c + 1].color, localNormalizedAxis);
                }                
            }
        }
    }

    text = new THREE.Mesh( geometry, materials );
    text.position.x = 0;
    text.position.y = 0;
    text.position.z = 0;

    text.rotation.x = -0.5;
    text.rotation.y = 0.6;
    text.rotation.z = 0.9;

    scene.add(text);
}

// funzione di rendering
// al suo interno è anche stabilita la rotazione dell'oggetto sul proprio asse y
var animate = function () {
    requestAnimationFrame( animate );
    
    //text.rotation.y += 0.001;
    // required if controls.enableDamping or controls.autoRotate are set to true
    controls.update();

    renderer.clear();
    renderer.render(scene, camera);
};
animate();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.js
  2. //threejs.org/examples/js/controls/OrbitControls.js