Three.js: Orientação CubeTexture

Criado em 25 abr. 2019  ·  31Comentários  ·  Fonte: mrdoob/three.js

Em meu aplicativo, gostaria de girar a CubeTexture que define o plano de fundo da cena e as reflexões do mapa do ambiente em 180 ° ao longo do eixo y vertical.
Minha rotação é definida pelas especificações VRML e X3D sobre os campos de fundo.

Tentei modificar vários parâmetros como os campos mapping , flipY e rotation Textura. No entanto, não encontrei uma boa maneira de o fazer.

  • Existe alguma maneira óbvia de fazer isso que eu esqueci?
  • Alguma chance de ver isso chegando em three.js ?
  • Se eu gostaria de implementá-lo, quais parâmetros você gostaria de ver (por exemplo Texture.flipX e CubeTexture.flipZ )? Você estaria interessado neste recurso?
Enhancement

Comentários muito úteis

Você quer dizer ser capaz de girar scene.background ? Se sim ... sim, definitivamente interessado.

Provavelmente precisamos de uma nova API ...

scene.background = new THREE.Background( cubeTexture );`
scene.background.rotation.y = Math.PI / 2;

Todos 31 comentários

Você quer dizer ser capaz de girar scene.background ? Se sim ... sim, definitivamente interessado.

Provavelmente precisamos de uma nova API ...

scene.background = new THREE.Background( cubeTexture );`
scene.background.rotation.y = Math.PI / 2;

Estou lutando exatamente com isso agora. Tentando obter sombras de solo cozidas para corresponder à direção do sol a partir de um mapa de cubos.
Parece que em algum lugar ao longo do caminho meu mapa de cubos está sendo girado 180 graus. Seria ótimo se eu pudesse apenas consertar isso aqui, em vez de renderizar novamente meu mapa de cubos várias vezes e tentar descobrir onde isso está acontecendo.

@fabienrohrer Experimente

scene.rotation.y = Math.PI;

Se isso não funcionar, forneça um exemplo ao vivo para demonstrar exatamente o que você está fazendo.

Oh, isso funciona? 😮 A câmera deve ser filha da cena, entretanto?

A câmera deve ser filha da cena?

Eu não acho que isso importe.

@mrdoob isso é exatamente o que eu preciso também :-)

@WestLangley :

Girar a cena geral é um exagero e pode causar muitos efeitos colaterais em meu aplicativo.

Gostaria de poder girar apenas o fundo e, com certeza, os mapas de ambiente deveriam funcionar da mesma forma.

Não é possível fazer uma demonstração ao vivo porque falta a API. É uma questão de pegar qualquer exemplo com um mapa de cubo de fundo (como https://threejs.org/examples/#webgl_materials_cubemap) e ser capaz de girar apenas o fundo em torno do eixo y. Ou, de forma mais geral, para aplicar qualquer rotação ao fundo.

Ser capaz de aplicar uma matriz / quatérnio de rotação customizada a qualquer mapa de cubo parece ser a solução mais genérica para mim.

three.js tem o cuidado de garantir que as reflexões do material sejam consistentes com o material envMap , que é definido no sistema de coordenadas do espaço mundial. Permitir que os usuários girem o plano de fundo da cena resultaria em um plano de fundo inconsistente com os reflexos do material.

Por que você não cria o mapa de cubos do espaço mundial correto em seu aplicativo?

A câmera deve ser filha da cena?

Eu não acho que isso importe.

Tentei fazer scene.rotation.y ++ no console em webgl_materials_standard e a arma gira. Então eu tentei fazer scene.add( camera ) e se eu fizer scene.rotation.y ++ ele fará o que queremos, mas então os controles da câmera bagunçam 😁

Se introduzirmos um objeto THREE.Background , poderíamos adicionar API para lidar com isso, além do renderizador, também podemos apresentar a ideia de:

var envMap = material.envMap;
if ( scene.background && scene.background.isBackground && envMap === null ) {
    envMap = scene.background.texture;
}

eu disse

Experimente scene.rotation.y = Math.PI; Se isso não funcionar, ...

Isso significa que pode não funcionar. :-)

Depende do caso de uso. Tentei com OrbitControls e funcionou bem.

não relacionado: o exemplo webgl_materials_standard deve estar usando controles de órbita, de qualquer maneira IMO.

Você quer dizer ser capaz de girar scene.background? Se sim ... sim, definitivamente interessado.

Faz mais sentido fazer isso no nível da textura, caso contrário, qualquer iluminação IBL não combinará com o fundo, eu presumo.

Nós permitimos a rotação de texturas normais, há alguma razão para não querermos fazer o mesmo com texturas de cubo? É muito complexo para implementar?

Por que você não cria o mapa de cubos do espaço mundial correto em seu aplicativo?

Isso é muito demorado. Tenho trabalhado na geração de mapas de cubo nos últimos dias, e fazer alterações e, em seguida, renderizar novamente o mapa de cubo leva cerca de 15-20 minutos para cada mudança.

Outro caso de uso interessante em potencial para isso é que você pode alterar a direção da iluminação ambiental em tempo real. No momento, estou combinando um mapa de ambiente PMREM com uma luz direcional para sombras em tempo real e usando o mapa como um skybox, o que dá um efeito de luz do dia bastante decente.
Obviamente, há um limite para o que você pode fazer sem alterar a cor do mapa do ambiente, mas você pode simular pelo menos algumas horas de luz do dia girando o mapa em sincronia com a luz direcional enquanto ajusta o .envMapIntensity .

Minha preocupação também é com o desempenho. Atualmente eu implementei um hack para girar a textura superior e inferior e trocar as outras. Demora cerca de 10ms para girar uma textura de 1024x1024 em JS.

Alternativamente, seria possível ter apenas duas opções para a orientação CubeTexture, a que você tem atualmente e outra (com a rotação de 180 graus) que seria compatível com o outro padrão amplamente utilizado em formatos 3D (X3D, VRML, etc .). Provavelmente poderíamos facilmente adaptar a consistência com reflexos de material para lidar com os dois formatos?

Isso soa familiar # 11103

Se eu implementasse CubeMap.rotation = matrix3 , você fundiria em r105?

Minha preocupação também é com o desempenho. Atualmente eu implementei um hack para girar a textura superior e inferior e trocar as outras. Demora cerca de 10ms para girar uma textura de 1024x1024 em JS.

E com que frequência você faz isso em seu aplicativo?

@WestLangley Acabei de lhe dar uma resposta detalhada aqui: https://github.com/mrdoob/three.js/pull/16507#discussion_r286337864

E com que frequência você faz isso em seu aplicativo?

Não muito. Uma vez no carregamento por cliente e uma vez a cada vez que o plano de fundo é alterado (caso muito raro). Um DEFINE também faria o trabalho.

Minha preocupação também é com o desempenho ... Demora cerca de 10ms.

E com que frequência você faz isso em seu aplicativo?

Não muito. Uma vez no carregamento por cliente e uma vez a cada vez que o plano de fundo é alterado (caso muito raro).

Desculpe, não estou seguindo a lógica disso.

Infelizmente, @WestLangley não deseja mesclar minha modificação sobre o CubeTexture.rotation por causa da sobrecarga do tempo de execução (uma multiplicação mat3 suplementar). Nesse caso, estou ficando sem ideias para resolver isso de forma limpa em três meses.
Se os colaboradores do threejs não resolverem isso, feche este problema.

Aguardo a implementação deste recurso.

@FishOrBear Infelizmente, os threejs mantenedores decidiram não implementar isso. Você poderia aplicar este patch não mesclado em uma bifurcação, se quiser ter isso em seu projeto:

https://github.com/mrdoob/three.js/pull/16507

@mrdoob Talvez possamos reconsiderar os pedidos de recurso em # 18157?

Estou usando threejs para fazer um aplicativo semelhante ao AutoCAD, então usamos xy para sentar como um avião.

A CubeTexture atual conflita um pouco com a nossa.

BTW: com Babylon.js, é pelo menos possível girar uma skybox em torno do eixo y:

https://www.babylonjs-playground.com/#UU7RQ # 447

O mecanismo suporta isso transformando o vetor de reflexão no sombreador de fragmento. Então, exatamente a abordagem que não foi aceita em # 16507. Código do shader de fragmento Babylon.js:

https://github.com/BabylonJS/Babylon.js/blob/1c4627141f83c08fe4a7e30e2621c916b4e6c9c9/src/Shaders/ShadersInclude/reflectionFunction.fx#L114 -L117

@mrdoob Acho que devemos implementar esse recurso. Há outro pedido no fórum:

https://discourse.threejs.org/t/rotate-a-scenes-background-skybox-texture/12199

Duvido que uma única multiplicação adicional de matriz / vetor por fragmento afete visivelmente o desempenho.

Ainda tenho o mesmo problema no meu aplicativo, e o hack para resolvê-lo é feio e muito caro ... Recomendo também aceitar essa melhoria.

Eu também adoraria ver esse recurso adicionado.

Parece que o bloqueador é uma diminuição potencial no desempenho, mas isso deve ser fácil de testar. Podemos tentar adicioná-lo e, se houver uma queda de desempenho inaceitável, podemos removê-lo novamente.

O mesmo aqui, poderia usar este recurso em vez de reimplementar minha renderização em segundo plano :)

Não tenho certeza de seguir no problema de desempenho. Nada nos impede de gerar a direção do raio diretamente no sombreador de vértice? Então, custaria tanto quanto qualquer outra transformação modelMatrix .

No meu caso, eu poderia usar esse recurso porque estou renderizando mapas de cubos capturados por câmeras e enviados por usuários. As fotos nem sempre estão orientadas para o norte corretamente, por isso precisam de uma correção manual após o upload.

Uma maneira de fazer isso é armazenar a rotação como uma variável, aplicá-la à cena antes da renderização e, em seguida, redefinir a rotação das cenas para a identidade quat logo após a renderização.

Isso causa duas atualizações desnecessárias em todas as matrizes de mundo de todos os meus objetos de cena. Isso também significa que não posso fazer nenhuma atualização de posição no onBeforeRender. Mas mantém a cena em um estado normal de outra forma.

A propósito (já que ninguém mencionou), parece ser possível fazer uma skybox "clássica" que gira usando uma matriz de 6 materiais.

algo assim :

const urls = [
  '/assets/skybox/right.png',
  '/assets/skybox/left.png',
  '/assets/skybox/top.png',
  '/assets/skybox/bottom.png',
  '/assets/skybox/front.png',
  '/assets/skybox/back.png',
];

const materials = urls.map((url) => {
  const texture = new THREE.TextureLoader().load(url);

  return new THREE.MeshBasicMaterial({
    map: texture,
    side: THREE.BackSide,
    fog: false,
    depthWrite: false,
  });
});

const skybox = new THREE.Mesh( new THREE.BoxBufferGeometry(10000, 10000, 10000), materials );
scene.add(skybox);

skybox.rotation.y = Math.PI / 2;

Conforme demonstrado aqui: https://woodenraft.games/demos/skybox-rotation-threejs.html

@wmcmurray Você terá que mover esta skybox com a câmera para que funcione direito, e você terá que se certificar de que sua caixa dimensione X <Math.sqrt (0.75 * camera.far * camera.far) para os cantos sempre cabem na visão, mas isso parece mais fácil do que meu hack de girar / cancelar a rotação da cena.

Devemos reabrir um PR para isso? Existem dois casos de uso e se não quisermos afetar o desempenho, podemos usar um shader define:

  • Caso de uso 1: o ambiente é pré-calculado uma vez e não deve ser girado no shader. Isso pode ser feito pelo usuário na CPU ou mesmo na GPU, se ele quiser
  • Caso de uso 2: ao trabalhar em um visualizador, é bastante comum girar o fundo em tempo real usando o mouse, por exemplo.

Para evitar que o usuário com o caso de uso 1 seja afetado pela multiplicação da matriz, talvez possamos simplesmente adicionar um sinalizador como:

renderer.dynamicBackground = true;

e compilar o sombreador de fundo de acordo?

Enquanto isso

Como @wmcmurray e @capnmidnight apontaram, você pode basicamente recodificar sua própria renderização de plano de fundo e não é tão difícil. Apenas tome cuidado extra com o plano de visualização (valores próximos e distantes).

Em vez de usar MeshBasicMaterial , você também pode criar diretamente seu próprio sombreador estendendo ShaderMaterial e obter uma amostra do mapa de cubo.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

ghost picture ghost  ·  3Comentários

jens-duttke picture jens-duttke  ·  3Comentários

filharvey picture filharvey  ·  3Comentários

boyravikumar picture boyravikumar  ·  3Comentários

Horray picture Horray  ·  3Comentários