gpt4 book ai didi

javascript - Three.js:初始渲染后更新作为 RawShaderMaterial 统一传递的纹理

转载 作者:太空宇宙 更新时间:2023-11-04 15:25:07 25 4
gpt4 key购买 nike

我有一个 Three.js 场景,它将 Canvas 作为制服传递给 RawShaderMaterial。初始场景渲染后,我更改 Canvas (在下面的情况下,我只是将 Canvas 涂成红色)。然后我指出 ShaderMaterial .needsUpdate = true;但点上没有出现颜色。

如果我移动ctx.fill();,颜色确实会出现在点上。 var material =上方循环声明。

有谁知道使用 RawShaderMaterial 时在初始渲染后必须做什么来更新 Canvas ?其他人可以提供的任何帮助都会非常有帮助!

<html>
<head>
<style>
html, body { width: 100%; height: 100%; background: #000; }
body { margin: 0; overflow: hidden; }
canvas { width: 100%; height: 100%; }
</style>
</head>
<body>
<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js'></script>
<script src='https://rawgit.com/YaleDHLab/pix-plot/master/assets/js/trackball-controls.js'></script>

<script type='x-shader/x-vertex' id='vertex-shader'>
precision highp float;

uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

uniform vec3 cameraPosition;

attribute vec3 position; // sets the blueprint's vertex positions
attribute vec3 translation; // x y translation offsets for an instance
attribute float texIdx; // the texture index to access

varying float vTexIdx;

void main() {
// set point position
vec3 pos = position + translation;
vec4 projected = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
gl_Position = projected;

// assign the varyings
vTexIdx = texIdx;

// use the delta between the point position and camera position to size point
float xDelta = pow(projected[0] - cameraPosition[0], 2.0);
float yDelta = pow(projected[1] - cameraPosition[1], 2.0);
float zDelta = pow(projected[2] - cameraPosition[2], 2.0);
float delta = pow(xDelta + yDelta + zDelta, 0.5);
gl_PointSize = 40000.0 / delta;
}
</script>

<script type='x-shader/x-fragment' id='fragment-shader'>
precision highp float;

uniform sampler2D a;
uniform sampler2D b;

varying float vTexIdx;

void main() {
int textureIndex = int(vTexIdx);
vec2 uv = vec2(gl_PointCoord.x, gl_PointCoord.y);
if (textureIndex == 0) {
gl_FragColor = texture2D(a, uv);
} else if (textureIndex == 1) {
gl_FragColor = texture2D(b, uv);
}
}
</script>

<script>

/**
* Generate a scene object with a background color
**/

function getScene() {
var scene = new THREE.Scene();
scene.background = new THREE.Color(0xaaaaaa);
return scene;
}

/**
* Generate the camera to be used in the scene
**/

function getCamera() {
var aspectRatio = window.innerWidth / window.innerHeight;
var camera = new THREE.PerspectiveCamera(75, aspectRatio, 0.1, 100000);
camera.position.set(0, 1, -6000);
return camera;
}

/**
* Generate the renderer to be used in the scene
**/

function getRenderer() {
// Create the canvas with a renderer
var renderer = new THREE.WebGLRenderer({antialias: true});
// Add support for retina displays
renderer.setPixelRatio(window.devicePixelRatio);
// Specify the size of the canvas
renderer.setSize(window.innerWidth, window.innerHeight);
// Add the canvas to the DOM
document.body.appendChild(renderer.domElement);
return renderer;
}

/**
* Generate the controls to be used in the scene
**/

function getControls(camera, renderer) {
var controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.zoomSpeed = 0.4;
controls.panSpeed = 0.4;
return controls;
}

/**
* Generate the points for the scene
**/

function addPoints(scene) {
var BA = THREE.BufferAttribute;
var IBA = THREE.InstancedBufferAttribute;
var geometry = new THREE.InstancedBufferGeometry();

// add data for each observation
var n = 10000; // number of observations
var rootN = n**(1/2);
var cellSize = 20;
var translation = new Float32Array( n * 3 );
var texIdx = new Float32Array( n );
var translationIterator = 0;
var texIterator = 0;
for (var i=0; i<n*3; i++) {
var x = Math.random() * n - (n/2);
var y = Math.random() * n - (n/2);
translation[translationIterator++] = x;
translation[translationIterator++] = y;
translation[translationIterator++] = Math.random() * n - (n/2);
texIdx[texIterator++] = (x + y) > (n/8) ? 1 : 0;
}

var positionAttr = new BA(new Float32Array( [0, 0, 0] ), 3);
var translationAttr = new IBA(translation, 3, 1);
var texIdxAttr = new IBA(texIdx, 1, 1);
positionAttr.dynamic = true;
translationAttr.dynamic = true;
texIdxAttr.dynamic = true;
geometry.addAttribute('position', positionAttr);
geometry.addAttribute('translation', translationAttr);
geometry.addAttribute('texIdx', texIdxAttr);

var canvases = [
getElem('canvas', { width: 16384, height: 16384, }),
getElem('canvas', { width: 16384, height: 16384, }),
];

var material = new THREE.RawShaderMaterial({
uniforms: {
a: {
type: 't',
value: getTexture(canvases[0]),
},
b: {
type: 't',
value: getTexture(canvases[1]),
}
},
vertexShader: document.getElementById('vertex-shader').textContent,
fragmentShader: document.getElementById('fragment-shader').textContent,
});
var mesh = new THREE.Points(geometry, material);
mesh.frustumCulled = false; // prevent the mesh from being clipped on drag
scene.add(mesh);

// Paint the canvas after the initial render
setTimeout(function() {
for (var i=0; i<canvases.length; i++) {
var canvas = canvases[i];
var ctx = canvas.getContext('2d');
ctx.fillStyle = i == 0 ? 'red' : 'blue';
ctx.rect(0, 0, 16384, 16384);
ctx.fill();
// marking the material as dirty does not make the colors appear
scene.children[0].material.needsUpdate = true;
}
}, 1000)
}

function getTexture(canvas) {
var tex = new THREE.Texture(canvas);
tex.needsUpdate = true;
tex.flipY = false;
return tex;
}

/**
* Create an element
**/

function getElem(tag, obj) {
var obj = obj || {};
var elem = document.createElement(tag);
Object.keys(obj).forEach(function(attr) {
elem[attr] = obj[attr];
})
return elem;
}

/**
* Render!
**/

function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
controls.update();
};

/**
* Main
**/

var scene = getScene();
var camera = getCamera();
var renderer = getRenderer();
var controls = getControls(camera, renderer);
addPoints(scene);
render();

</script>
</body>
</html>

最佳答案

啊,必须重新分配制服的值(存储在 Material 中),然后将 Material 标记为需要更新:

scene.children[0].material.uniforms.a.value = getTexture(canvases[0]);
scene.children[0].material.uniforms.b.value = getTexture(canvases[1]);
scene.children[0].material.needsUpdate = true;

关于javascript - Three.js:初始渲染后更新作为 RawShaderMaterial 统一传递的纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51540596/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com