Одной из возможностей является использование Three.DataTexture
.
Буфер данных, который предоставляется для Three.DataTexture
, должен иметь тип Uint8Array
, а не Uint8ClampedArray
.Это упоминается в документации.
Буфер должен состоять из байтовых значений в диапазоне [0, 255]:
например,
let t_cx = 512;
let t_cy = 512;
let t_data = new Uint8Array(4 * t_cx * t_cy);
for ( let i = 0; i < t_cx; i ++ ) {
for ( let j = 0; j < t_cy; j ++ ) {
let id = j*t_cx*4 + i*4;
let r = i / (t_cx-1);
let g = j / (t_cx-1);
let b = (1-r)*(1-g);
t_data[id + 0] = r * 255;
t_data[id + 1] = g * 255;
t_data[id + 2] = b * 255;
t_data[id + 3] = 255;
}
}
Более того, свойство .needsUpdate
должен быть установлен true
для вновь созданного объекта текстуры.
var texture = new THREE.DataTexture( t_data, t_cx, t_cy, THREE.RGBAFormat );
texture.needsUpdate = true;
Также возможно создать временный 2D-холст и объект изображения.Это может быть загружено THREE.TextureLoader
как обычно:
let canvas = document.createElement( 'canvas' );
let ctx = canvas.getContext('2d');
canvas.width = t_cx;
canvas.height = t_cy;
let idata = ctx.createImageData( t_cx, t_cy );
idata.data.set( t_data );
ctx.putImageData( idata, 0, 0 );
let dataUri = canvas.toDataURL();
var texture = new THREE.TextureLoader().load( dataUri );
canvas.remove();
См. Пример:
(function onLoad() {
var loader, camera, scene, renderer, orbitControls;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, 1, -2);
//camera.lookAt( -1, 0, 0 );
loader = new THREE.TextureLoader();
loader.setCrossOrigin("");
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = resize;
var ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set(1,2,1.5);
scene.add( directionalLight );
orbitControls = new THREE.OrbitControls(camera);
addGridHelper();
createModel();
}
function createModel() {
let t_cx = 512;
let t_cy = 512;
let t_data = new Uint8Array(4 * t_cx * t_cy);
for ( let i = 0; i < t_cx; i ++ ) {
for ( let j = 0; j < t_cy; j ++ ) {
let id = j*t_cx*4 + i*4;
let r = i / (t_cx-1);
let g = j / (t_cx-1);
let b = (1-r)*(1-g);
t_data[id + 0] = r * 255;
t_data[id + 1] = g * 255;
t_data[id + 2] = b * 255;
t_data[id + 3] = 255;
}
}
var testMode = 1
var texture;
if ( testMode == 1 ) {
let canvas = document.createElement( 'canvas' );
let ctx = canvas.getContext('2d');
canvas.width = t_cx;
canvas.height = t_cy;
let idata = ctx.createImageData( t_cx, t_cy );
idata.data.set( t_data );
ctx.putImageData( idata, 0, 0 );
let dataUri = canvas.toDataURL();
texture = new THREE.TextureLoader().load( dataUri );
canvas.remove();
} else {
texture = new THREE.DataTexture( t_data, t_cx, t_cy, THREE.RGBAFormat );
texture.needsUpdate = true;
}
var material = new THREE.ShaderMaterial({
vertexShader: document.getElementById('vertex-shader').textContent,
fragmentShader: document.getElementById('fragment-shader').textContent,
uniforms : {
buffer: {type: 't', value: texture}
}
});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function addGridHelper() {
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<script type='x-shader/x-vertex' id='vertex-shader'>
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script type='x-shader/x-fragment' id='fragment-shader'>
precision highp float;
uniform sampler2D buffer;
varying vec2 vUv;
void main(){
gl_FragColor = texture2D(buffer, vUv);
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>