Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

98
Vistas
planeGeometry turned into a sphere

I feel like my logic isnt too awful here. I am trying to convert a planeGeometry into a sphere using its UV coordinates as latitude and longitude. Essentially here is the logic:

  1. convert uv coordinates to lat/long respectively
  2. change lat/long over to radians
  3. convert to x,y,z catesian coordinates

heres the code for the vertex shader im trying out:

    varying vec2 vUv;

    #define PI 3.14159265359

    void main() {
      vUv = uv;

      float lat = (uv.x - 0.5) * 90.0;
      float lon = abs((uv.y - 0.5) * 180.0);

      float latRad = lat * (PI / 180.0);
      float lonRad = lon * (PI / 180.0);

      float x = sin(latRad) * sin(lonRad);
      float y = cos(latRad);
      float z = cos(latRad) * sin(lonRad);

      gl_Position = projectionMatrix * modelViewMatrix * vec4(x,y,z, 0.5);
    }

Any advice is appreciated, I feel like I am just missing something small with the logic but I believe in the masses.

Edit:

The problem ended up being pretty stupid, I was just passing the wrong values for the planeGeometry arguments. All solutions here are valid.

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

This is how THREE.js does it:

setFromSphericalCoords( radius, phi, theta ) {

    const sinPhiRadius = Math.sin( phi ) * radius;

    this.x = sinPhiRadius * Math.sin( theta );
    this.y = Math.cos( phi ) * radius;
    this.z = sinPhiRadius * Math.cos( theta );

    return this;
}

Based on this, it looks like your z line is switched. Try:

float z = sin(latRad) * cos(lonRad);

I also don't understand the point of using 0.5 when declaring your position vector4. Just use 1.0: vec4(x,y,z, 1.0);

Finally, you're complicating things by going to degrees, then back to radians when multiplying *90 and then dividing /180. If you already have [0, 1] range, just multiply by PI and PI * 2 accordingly to convert to radians.

about 4 years ago · Juan Pablo Isaza Denunciar

0

I always use that implementation of spherical coords from three.js in shaders, if I want to morph plane to sphere:

body{
  overflow: hidden;
  margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import { OrbitControls } from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls.js";
import { GUI } from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/libs/lil-gui.module.min.js";

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 1).setLength(6);
let renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(innerWidth, innerHeight);
renderer.setClearColor(0x404040);
document.body.appendChild(renderer.domElement);

let controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.update();
console.log(controls.getAzimuthalAngle())

let light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0.25, 0.5, 1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));

let u = {
    mixVal: {value: 0}
}

let g = new THREE.PlaneGeometry(2 * Math.PI, Math.PI, 100, 100);
let m = new THREE.MeshBasicMaterial({
    map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/uv_grid_opengl.jpg"),
  onBeforeCompile: shader => {
    shader.uniforms.mixVal = u.mixVal;
    shader.vertexShader = `
        uniform float mixVal;
      vec3 fromSpherical(float radius, float phi, float theta){
        float sinPhiRadius = sin( phi ) * radius;

        float x = sinPhiRadius * sin( theta );
        float y = cos( phi ) * radius;
        float z = sinPhiRadius * cos( theta );

        return vec3(x, y, z);
      }
      ${shader.vertexShader}
    `.replace(
        `#include <begin_vertex>`,
      `#include <begin_vertex>
        float phi = (1. - uv.y) * PI;
        float theta = uv.x * PI * 2. + PI;
        float r = 1.;
        transformed = mix(position, fromSpherical(r, phi, theta), mixVal);
      `
    );
    //console.log(shader.vertexShader);
  }
});
let box = new THREE.Mesh(g, m);
scene.add(box);

let gui = new GUI();
gui.add(u.mixVal, "value", 0, 1).name("mixVal");

window.addEventListener("resize", onWindowResize);

renderer.setAnimationLoop(() => {
    renderer.render(scene, camera);
})

function onWindowResize() {

  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(innerWidth, innerHeight);

}
</script>

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda