我可以使用6个单独的图像文件制作一个three.js天空盒。但我希望能够从由瓷砖组成的单个图像构建天空盒。
例如,如果我有一个复合平铺图像作为源(请参阅(http://www.zen226082.zen.co.uk/STACK_EXCHANGE/Giant_A.jpg)...我没有足够的代表在这里发布它: - (。
我可以将合成图像加载到画布中,并将每个图块复制到缓存缓冲区中,然后将它们发送到Three.js材质数组中。然后使用这些材料制作一个天空盒。
但是有两个问题。
问题1是需要翻转合成图像。我可以在像Paint.net这样的图形应用程序中轻松实现这一点,但能够以javascript / three.js编程方式进行操作会很棒。
问题2是Three.js要求Y +和Y-的瓷砖也需要旋转180度。在图形应用程序中这很难(对我而言)。例如,这是修改后的复合平铺图像,以适应我一直使用的Three.js代码(http://www.zen226082.zen.co.uk/STACK_EXCHANGE/Giant_B.jpg)(可怕!)
我的问题=在从合成图像中提取并在将它们传递到天空盒构造之前,我可以通过某种方式对两个图块执行180度旋转。
EDIT(2014年8月10日) 问题应该是"如何从由12个相等大小的瓷砖组成的单个图像文件制作一个three.js skyBox"。
以下是我一直使用的代码: -
var skyBoxGeometry = new THREE.CubeGeometry(skybox_sidelength,skybox_sidelength,skybox_sidelength);
var skyBoxMaterialArray = [];
var widthOfOnePiece = 2048/4;//...i.e. 512
var heightOfOnePiece = 1536/3;//...i.e. 512
var numColsToCut = 4;
var numRowsToCut = 3;
var image = new Image();
image.src = "TRI_VP_files/images/SOW_skybox_2048_1536_v7.jpg";
image.onload = SOW_F_cutImageUp;
//... NB canvas origin is Top Left corner, X is left to right, Y is top to bottom
function SOW_F_cutImageUp() {
var imagePieces = [];
for(var xxx = 0; xxx < numColsToCut; ++xxx)
{
for(var yyy = 0; yyy < numRowsToCut; ++yyy)
{
var canvas = document.createElement('canvas');
canvas.width = widthOfOnePiece;
canvas.height = heightOfOnePiece;
var context = canvas.getContext('2d');
context.drawImage(image,
xxx * widthOfOnePiece, yyy * heightOfOnePiece, widthOfOnePiece, heightOfOnePiece, 0, 0, canvas.width, canvas.height);
imagePieces.push(canvas.toDataURL());
}
}
//... expected sequence of face view directions = ["xpos", "xneg", "ypos", "yneg", "zpos", "zneg"];
for (var iii = 0; iii < 6; iii++)
{
if (iii == 0) imagePiece_num = 4 //... xpos
else if (iii == 1) imagePiece_num = 10//... xneg
else if (iii == 2) imagePiece_num = 6 //... ypos
else if (iii == 3) imagePiece_num = 8 //... yneg
else if (iii == 4) imagePiece_num = 1 //... zpos
else if (iii == 5) imagePiece_num = 7 //... zneg
skyBoxMaterialArray.push
( new THREE.MeshBasicMaterial
( {map: THREE.ImageUtils.loadTexture(imagePieces[imagePiece_num]),
side: THREE.BackSide}));
//window.open(imagePieces[imagePiece_num], "Here is the toDataURL() cached image", "width=512, height=512");
//alert ("Continue");
}
}//... end of function.
var skyBoxMaterial = new THREE.MeshFaceMaterial( skyBoxMaterialArray );
var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );
scene222.add( skyBox );
答案 0 :(得分:0)
问题应该是“如何从由12个相等大小的瓷砖组成的单个图像文件制作一个three.js skyBox”。
(这个答案得到了WestLangley非常感谢的帮助)。
一些关键点: -
假设源图像中的图块被排列和引用: -
//... Personal Source image Desired in-scene Required
//... tile numbering [column, row] xyz positions of 6 sequence numbers in
//... scheme tile coordinates tiles to be used. Three.js material array
//... [ 0] [ 3] [ 6] [ 9] [0,0] [1,0] [2,0] [3,0] [ ] [py] [ ] [ ] [ ] [2] [ ] [ ]
//... [ 1] [ 4] [ 7] [10] [0,1] [1,1] [2,1] [3,1] [nx] [pz] [px] [nz] [1] [4] [0] [5]
//... [ 2] [ 5] [ 8] [11] [0,2] [1,2] [2,2] [3,2] [ ] [ny] [ ] [ ] [ ] [3] [ ] [ ]
“十字”中心的图块对应于从天空框原点沿Z_正方向查看的视图。
(这使得旋转180度不必要)。
在材料使用的定义中...方:THREE.FrontSide
要防止源图块的镜像,请使用... skyBox.scale.set(-1,1,1)“翻转”它们
为了确保图像得到完全处理,函数F_cutImageUp扩展为包括创建skyBox网格
这适用于当前最新的Three.js版本(R.68)。
此代码不使用MeshShaderMaterial,更强大(但要求更高)的WebGL代码示例位于http://threejs.org/examples/webgl_shaders_ocean.html
webgl_shaders_ocean.html代码示例还包含更高效的切片和排序算法。
SkyBox生成代码(插入THREE.js初始化函数)。
var skybox_sidelength = 10000;
var skyBoxGeometry = new THREE.BoxGeometry( skybox_sidelength, skybox_sidelength, skybox_sidelength);
var skyBoxMaterialArray = [];
var numCols = 4, numRows = 3; //... assume any source image is tiled 4 columns(x) by 3 rows(y)
//... NB canvas origin is Top Left corner, X is left to right, Y is top to bottom
//... We use the following mapping scheme to reference the tiles in the source image:-
//...
//... Personal [x,y] tile coordinates xyz positions Required tile
//... tile numbering of tiles in scene sequence in Three.js
//... array
//... [ 0] [ 3] [ 6] [ 9] [0,0] [1,0] [2,0] [3,0] [ ] [py] [ ] [ ] [ ] [2] [ ] [ ]
//... [ 1] [ 4] [ 7] [10] [0,1] [1,1] [2,1] [3,1] [nx] [pz] [px] [nz] [1] [4] [0] [5]
//... [ 2] [ 5] [ 8] [11] [0,2] [1,2] [2,2] [3,2] [ ] [ny] [ ] [ ] [ ] [3] [ ] [ ]
var image_file = "3D_Skybox_files/Giant_A.jpg", tile_width = 512, tile_height = 512;
var IP_image = new Image();
IP_image.onload = F_cutImageUp;
IP_image.src = image_file; //... horizontal cross of 6 WYSIWYG tiles in a 4x3 = 12 tile layout.
function F_cutImageUp()
{ //... cut up source image into 12 separate image tiles, numbered 0..11
var imagePieces = [];
var item_num = -1;
for(var xxx = 0; xxx < numCols; ++xxx)
{
for(var yyy = 0; yyy < numRows; ++yyy)
{
var tileCanvas = document.createElement('canvas');
tileCanvas.width = tileWidth;
tileCanvas.height = tileHeight;
var tileContext = tileCanvas.getContext('2d');
tileContext.drawImage(
IP_image,
xxx * tileWidth, yyy * tileHeight,
tileWidth, tileHeight,
0, 0, tileCanvas.width, tileCanvas.height);
imagePieces.push(tileCanvas.toDataURL());
}
}
//... Required sequence of tile view directions = ["xpos", "xneg", "ypos", "yneg", "zpos", "zneg"];
for (var iii = 0; iii < 6; iii++) //... select the right tiles for the 6 different faces of the sky box
{
//... we associate the centre tile (4) of the cross with the zpos direction
if (iii == 0) imagePiece_num = 7;//... xpos
else if (iii == 1) imagePiece_num = 1;//... xneg
else if (iii == 2) imagePiece_num = 3;//... ypos
else if (iii == 3) imagePiece_num = 5;//... yneg
else if (iii == 4) imagePiece_num = 4;//... zpos
else if (iii == 5) imagePiece_num = 10;//... zneg
skyBoxMaterialArray.push
( new THREE.MeshBasicMaterial
({ map: THREE.ImageUtils.loadTexture(imagePieces[imagePiece_num]),
side: THREE.FrontSide // <== not intuitive
})
);
//... Just for checking image pieces are created OK
//window.open(imagePieces[imagePiece_num], "Here is the toDataURL() cached image " + //imagePiece_num, "width=512, height=512");
//alert ("Displayed imagePiece_num: " + imagePiece_num);
} //... end of tile selection
var skyBoxMaterial = new THREE.MeshFaceMaterial( skyBoxMaterialArray );
var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );
skyBox.scale.set( -1, 1, 1 ); // <== not intuitive
scene.add( skyBox );
}//... end of F_cutImageUp function <== note function includes skyBox mesh creation.