THREE.js에서 텍스처 사용
저는 THREE.js로 시작하고 단일 광원으로 비추는 텍스처가있는 사각형을 그리려고합니다. 나는 이것이 얻는 것처럼 간단하다고 생각합니다 (간결성을 위해 HTML이 생략되었습니다).
function loadScene() {
var world = document.getElementById('world'),
WIDTH = 1200,
HEIGHT = 500,
VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000,
renderer = new THREE.WebGLRenderer(),
camera = new THREE.Camera(VIEW_ANGLE, ASPECT, NEAR, FAR),
scene = new THREE.Scene(),
texture = THREE.ImageUtils.loadTexture('crate.gif'),
material = new THREE.MeshBasicMaterial({map: texture}),
// material = new THREE.MeshPhongMaterial({color: 0xCC0000});
geometry = new THREE.PlaneGeometry(100, 100),
mesh = new THREE.Mesh(geometry, material),
pointLight = new THREE.PointLight(0xFFFFFF);
camera.position.z = 200;
renderer.setSize(WIDTH, HEIGHT);
scene.addChild(mesh);
world.appendChild(renderer.domElement);
pointLight.position.x = 50;
pointLight.position.y = 50;
pointLight.position.z = 130;
scene.addLight(pointLight);
renderer.render(scene, camera);
}
문제는 아무것도 볼 수 없다는 것입니다. 재질을 변경하고 주석이 달린 것을 사용하면 예상대로 사각형이 나타납니다. 참고
- 텍스처는 256x256이므로 측면은 2의 제곱입니다.
- 이 함수는 실제로 본문이로드 될 때 호출됩니다. 실제로 다른 재료로 작동합니다.
- 웹 서버에서 파일을 제공해도 작동하지 않으므로 이미지로드를 허용하지 않는 도메인 간 정책 문제가 아닙니다.
내가 뭘 잘못하고 있니?
이미지가로드 될 때까지 렌더러가 이미 장면을 그렸으므로 너무 늦었습니다. 해결책은 변화하는 것입니다
texture = THREE.ImageUtils.loadTexture('crate.gif'),
으로
texture = THREE.ImageUtils.loadTexture('crate.gif', {}, function() {
renderer.render(scene);
}),
Andrea 솔루션은 절대적으로 옳습니다. 동일한 아이디어를 기반으로 다른 구현을 작성하겠습니다. THREE.ImageUtils.loadTexture () 소스 를 살펴보면 javascript Image 객체를 사용하는 것을 알 수 있습니다. 모든 이미지가로드 된 후 $ (window) .load 이벤트가 시작됩니다! 그 이벤트에서 이미로드 된 텍스처로 장면을 렌더링 할 수 있습니다.
CoffeeScript
$(document).ready -> material = new THREE.MeshLambertMaterial(map: THREE.ImageUtils.loadTexture("crate.gif")) sphere = new THREE.Mesh(new THREE.SphereGeometry(radius, segments, rings), material) $(window).load -> renderer.render scene, camera자바 스크립트
$(document).ready(function() { material = new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture("crate.gif") }); sphere = new THREE.Mesh(new THREE.SphereGeometry(radius, segments, rings), material); $(window).load(function() { renderer.render(scene, camera); }); });
감사...
three.js의 r75 버전에서는 다음을 사용해야합니다.
var loader = new THREE.TextureLoader();
loader.load('texture.png', function ( texture ) {
var geometry = new THREE.SphereGeometry(1000, 20, 20);
var material = new THREE.MeshBasicMaterial({map: texture, overdraw: 0.5});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
});
Three.js의 r82 버전에서 TextureLoader 는 텍스처를로드하는 데 사용할 개체입니다.
하나의 텍스처로드 ( 소스 코드 , 데모 )
추출 ( test.js ) :
var scene = new THREE.Scene();
var ratio = window.innerWidth / window.innerHeight;
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight,
0.1, 50);
var renderer = ...
[...]
/**
* Will be called when load completes.
* The argument will be the loaded texture.
*/
var onLoad = function (texture) {
var objGeometry = new THREE.BoxGeometry(20, 20, 20);
var objMaterial = new THREE.MeshPhongMaterial({
map: texture,
shading: THREE.FlatShading
});
var mesh = new THREE.Mesh(objGeometry, objMaterial);
scene.add(mesh);
var render = function () {
requestAnimationFrame(render);
mesh.rotation.x += 0.010;
mesh.rotation.y += 0.010;
renderer.render(scene, camera);
};
render();
}
// Function called when download progresses
var onProgress = function (xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
};
// Function called when download errors
var onError = function (xhr) {
console.log('An error happened');
};
var loader = new THREE.TextureLoader();
loader.load('texture.jpg', onLoad, onProgress, onError);
여러 텍스처로드 ( 소스 코드 , 데모 )
이 예제에서는 텍스처가 메시 생성자 내부에로드되고 Promises를 사용하여 여러 텍스처가로드됩니다 .
추출 ( Globe.js ) :
Object3D동일한 컨테이너에 두 개의 메시가있는 경우를 사용하여 새 컨테이너를 만듭니다 .
var Globe = function (radius, segments) {
THREE.Object3D.call(this);
this.name = "Globe";
var that = this;
// instantiate a loader
var loader = new THREE.TextureLoader();
textures모든 객체가 url텍스처 파일 val을 포함하고 Three.js 텍스처 객체 의 값을 저장하기 위해 호출 되는 맵 입니다.
// earth textures
var textures = {
'map': {
url: 'relief.jpg',
val: undefined
},
'bumpMap': {
url: 'elev_bump_4k.jpg',
val: undefined
},
'specularMap': {
url: 'wateretopo.png',
val: undefined
}
};
promise의 배열은 texturespush a new Promise in the array 라는 맵의 각 객체에 대해 texturePromises모든 Promise가를 호출 loader.load합니다. 의 값이 entry.val유효한 THREE.Texture객체이면 약속을 해결합니다.
var texturePromises = [], path = './';
for (var key in textures) {
texturePromises.push(new Promise((resolve, reject) => {
var entry = textures[key]
var url = path + entry.url
loader.load(url,
texture => {
entry.val = texture;
if (entry.val instanceof THREE.Texture) resolve(entry);
},
xhr => {
console.log(url + ' ' + (xhr.loaded / xhr.total * 100) +
'% loaded');
},
xhr => {
reject(new Error(xhr +
'An error occurred loading while loading: ' +
entry.url));
}
);
}));
}
Promise.all약속 배열 texturePromises을 인수로 사용합니다. 이렇게하면 브라우저가 모든 약속이 해결 될 때까지 기다릴 수 있으며, 해결 될 때 지오메트리와 재질을로드 할 수 있습니다.
// load the geometry and the textures
Promise.all(texturePromises).then(loadedTextures => {
var geometry = new THREE.SphereGeometry(radius, segments, segments);
var material = new THREE.MeshPhongMaterial({
map: textures.map.val,
bumpMap: textures.bumpMap.val,
bumpScale: 0.005,
specularMap: textures.specularMap.val,
specular: new THREE.Color('grey')
});
var earth = that.earth = new THREE.Mesh(geometry, material);
that.add(earth);
});
구름 구의 경우 하나의 텍스처 만 필요합니다.
// clouds
loader.load('n_amer_clouds.png', map => {
var geometry = new THREE.SphereGeometry(radius + .05, segments, segments);
var material = new THREE.MeshPhongMaterial({
map: map,
transparent: true
});
var clouds = that.clouds = new THREE.Mesh(geometry, material);
that.add(clouds);
});
}
Globe.prototype = Object.create(THREE.Object3D.prototype);
Globe.prototype.constructor = Globe;
TextureLoader를 사용하여 이미지를 텍스처로로드 한 다음 해당 텍스처를 장면 배경에 적용하면됩니다.
new THREE.TextureLoader();
loader.load('https://images.pexels.com/photos/1205301/pexels-photo-1205301.jpeg' , function(texture)
{
scene.background = texture;
});
결과:
https://codepen.io/hiteshsahu/pen/jpGLpq?editors=0011
펜 참조 평면 지구 three.js를 Hitesh Sahu (기준 @hiteshsahu 에) CodePen을 .오류 처리없이
//Load background texture
new THREE.TextureLoader();
loader.load('https://images.pexels.com/photos/1205301/pexels-photo-1205301.jpeg' , function(texture)
{
scene.background = texture;
});
오류 처리 포함
// Function called when download progresses
var onProgress = function (xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
};
// Function called when download errors
var onError = function (error) {
console.log('An error happened'+error);
};
//Function called when load completes.
var onLoad = function (texture) {
var objGeometry = new THREE.BoxGeometry(30, 30, 30);
var objMaterial = new THREE.MeshPhongMaterial({
map: texture,
shading: THREE.FlatShading
});
var boxMesh = new THREE.Mesh(objGeometry, objMaterial);
scene.add(boxMesh);
var render = function () {
requestAnimationFrame(render);
boxMesh.rotation.x += 0.010;
boxMesh.rotation.y += 0.010;
sphereMesh.rotation.y += 0.1;
renderer.render(scene, camera);
};
render();
}
//LOAD TEXTURE and on completion apply it on box
var loader = new THREE.TextureLoader();
loader.load('https://upload.wikimedia.org/wikipedia/commons/thumb/9/97/The_Earth_seen_from_Apollo_17.jpg/1920px-The_Earth_seen_from_Apollo_17.jpg',
onLoad,
onProgress,
onError);
결과:
https://codepen.io/hiteshsahu/pen/jpGLpq/
참고 URL : https://stackoverflow.com/questions/7919516/using-textures-in-three-js
'Program Club' 카테고리의 다른 글
| matplotlib에서 줄 바꿈이있는 텍스트 상자? (0) | 2020.11.04 |
|---|---|
| 환경 설정이 변경되었는지 감지하는 방법은 무엇입니까? (0) | 2020.11.04 |
| RestTemplate을 사용할 때 내부 Jackson 매퍼를 어떻게 구성 할 수 있습니까? (0) | 2020.11.04 |
| cmd 파일에서 %와 %%의 차이점은 무엇입니까? (0) | 2020.11.04 |
| Node.js에서 POST 요청을 사용하여 파일 업로드 (0) | 2020.11.04 |
