现在我有了数组:Uint8ClampedArray(size:512*512*4)
,我想将此数组转换为three.js中的纹理,然后使用Three.ShaderMaterial
渲染对象。
new THREE.ShaderMaterial( {
vertexShader: document.querySelector( '#blendModel-vert').textContent.trim(),
fragmentShader: document.querySelector( '#blendModel-frag' ).textContent.trim(),
uniforms: {
buffer: { value: texture },
}
});
着色器如下:
<script id="blendModel-vert" type="x-shader/x-vertex">
varying vec2 vUv;
varying vec4 gPosition;
void main() {
vUv = uv;
gPosition=gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script id="blendModel-frag" type="x-shader/x-fragment">
varying vec2 vUv;
uniform sampler2D buffer;
varying vec4 gPosition;
void main() {
gl_FragColor.rgb = texture2D(buffer, vUv).rgb;
gl_FragColor.a = 1.0;
}
</script>
答案 0 :(得分:0)
一种可能性是使用https://reactjs.org/docs/state-and-lifecycle.html。
提供给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;
}
}
此外,必须在新创建的纹理对象上将属性Three.DataTexture
设置为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>