我用的是三。InstancedBufferGeometry,我希望访问顶点着色器中编码为纹理的数据。
我想做的是,创建一个每个实例一个像素的数据纹理,它将存储每个实例的位置数据(然后在稍后的阶段,我可以使用带有流场的模拟来更新纹理,以设置位置动画)。
我正在努力从顶点着色器中的纹理访问数据。
const INSTANCES_COUNT = 5000;
// FOR EVERY INSTANCE, GIVE IT A RANDOM X, Y, Z OFFSET, AND SAVE IT IN DATA TEXTURE
const data = new Uint8Array(4 * INSTANCES_COUNT);
for (let i = 0; i < INSTANCES_COUNT; i++) {
const stride = i * 4;
data[stride] = (Math.random() - 0.5);
data[stride + 1] = (Math.random() - 0.5);
data[stride + 2] = (Math.random() - 0.5);
data[stride + 3] = 0.0;
}
const offsetTexture = new THREE.DataTexture( data, INSTANCES, 1, THREE.RGBAFormat, THREE.FloatType );
offsetTexture.minFilter = THREE.NearestFilter;
offsetTexture.magFilter = THREE.NearestFilter;
offsetTexture.generateMipmaps = false;
offsetTexture.needsUpdate = true;
// CREATE MY INSTANCED GEOMETRY
const geometry = new THREE.InstancedBufferGeometry();
geometry.maxInstancedCount = INSTANCES_COUNT;
geometry.addAttribute( 'position', new THREE.Float32BufferAttribute([5, -5, 0, -5, 5, 0, 0, 0, 5], 3 )); // SIMPLE TRIANGLE
const vertexShader = `
precision highp float;
uniform vec3 color;
uniform sampler2D offsetTexture;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
varying vec3 vPosition;
varying vec3 vColor;
void main(){
vPosition = position;
vec4 orientation = vec4(.0, .0, .0, .0);
vec3 vcV = cross( orientation.xyz, vPosition );
vPosition = vcV * ( 2.0 * orientation.w ) + ( cross( orientation.xyz, vcV ) * 2.0 + vPosition );
vec2 uv = position.xy;
vec4 data = texture2D( offsetTexture, uv );
vec3 particlePosition = data.xyz * 1000.0;
gl_Position = projectionMatrix * modelViewMatrix * vec4( vPosition + particlePosition, 1.0 );
}
`;
const fragmentShader = `
precision highp float;
varying vec3 vColor;
void main() {
gl_FragColor = vec4(vColor, 1.0);
}
`;
const uniforms = {
size: { value: 1.0 },
color: {
type: 'c',
value: new THREE.Color(0x3db230),
},
offsetTexture: {
type: 't',
value: offsetTexture,
},
};
// CREATE MY MATERIAL
const material = new THREE.RawShaderMaterial({
uniforms,
vertexShader,
fragmentShader,
side: THREE.DoubleSide,
transparent: false,
});
scene.add(new THREE.Mesh(geometry, material));
目前,图像中的数据似乎无法在顶点着色器中访问(例如,如果我只是将vUv设置为vec2(1.0,0.0),并更改偏移位置,则不会发生任何更改),而且我不确定如何确保实例可以引用纹理中的正确纹理。
此外,我是否必须规范化数据(0.0-1.0,或0-255,或-1-
谢谢
你需要对每个实例的纹理计算某种索引。也就是说,您需要一个将由每个实例共享的属性。
如果你的三角形是
[a,b,c]
你的索引应该是
[0,0,0]
假设有1024个实例和1024x1像素的纹理。
attribute float aIndex;
vec2 myIndex = ((aIndex + 0.5)/1024.,1.);
vec4 myRes = texture2D( mySampler, myIndex);
在课程的第二章对Threejs几何体Geometry和BufferGeometry的顶点概念做过比较多的介绍,讲解过顶点位置坐标数据、顶点颜色数据、顶点法线方向向量数据,不过顶点的UV数据没有去讲解,主要是几何体顶点的纹理坐标数据和纹理贴图的映射有关系,所以放在了本章节去讲解。 纹理UV坐标 纹理坐标含义就是一面意思,一张纹理贴图图像的坐标,选择一张图片,比如以图片左下角为坐标原点,右上角为坐标(
我用C SDL2 GLEW Opengl 4.1编程一个小的体素游戏,有点像Minecraft。 我正在尽可能优化体素渲染。 我把世界滑成一块块,而这块块又滑成一块块。 每个块包含16x16x16个块。 现在,如果编辑块(删除/放置块),我将重建完整块和相邻块,并将其与vao和vbo一起上载到图形卡。 现在,为了最小化顶点数据,我必须从cpu传输到gpu,我使用几何体着色器。 首先,这是个好主意吗
我能够使用javascript和three.js库创建一个球体。然而,我有一个图像,我想覆盖在球体的顶部,每当我这样做,球体变成一个黑色的球体,没有图像投射在上面。下面是我如何实现它:var渲染器=new THREE. WebGL渲染器();renderer.set大小(window.inner宽度,window.inner高度);document.body.append(renderer.dom
使用GLE管材和挤出库(http://www.linas.org/gle/)我能够使用OpenGL将2D计数挤出到3D对象中。该库在CPU上完成所有工作,并使用OpenGL即时模式。 我想在GPU上使用几何着色器进行挤压可能会更快,尤其是在渲染大量几何图形时。因为我还没有在OpenGL中使用几何着色器的任何经验,我想知道这是否可能,以及我必须注意什么。您认为将这些计算转移到GPU并提高性能是个好主
我正在尝试制作一个几何体着色器(使用着色器生成器)来简化模型。首先,我试图做一个体素化,但结果不好,我找不到它的错。 在下面的代码中,想法是找到输入三角形的中心,然后使其成为我要创建的框的中心。 我知道这不是世界上最优雅的代码,但先走一步,我需要让它工作...
我正在OpenGL中练习纹理,将定义为白色的简单纹理应用到四边形上。代码编译和运行良好,但四元体的颜色只是黑色,而不是我指定的白色。 我认为这是因为我的片段着色器没有进行正确的采样,就像它从纹理函数返回的数据都是零,因此四边形的纹理变为黑色。我之所以这么想,是因为当我运行程序时,我可以把白色变成清晰的颜色,并稍微移动四边形上的一个顶点,以便看到背景(因为它通常会填充整个曲面)。然后我可以清楚地看到