如何在保持 WebGL GLSL 中心的同时缩放 3D 立方体?
How can I scale a 3D Cube while maintaining it's center in WebGL GLSL?
我有一个比例属性,就像我在三个 js 中应用于 instance buffered geometry 的不同实例一样。着色器看起来像这样:
attribute float scale;
uniform vec3 uMeshPosition;
void main() {
vec3 pos = position;
pos.x *= ( uMeshPosition.x - pows.x ) * scale + uMeshPosition.x;
pos.z *= ( uMeshPosition.z - pos.z ) * scale + uMeshPosition.z;
pos.y *= ( uMeshPosition.y - pos.y ) * scale + uMeshPosition.y;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1.0);
}
Z是我的身高!!!
我希望缩放的立方体保持上面线框立方体指示的初始中心。
是否可以在不计算和应用缩放的情况下在所有 3 个轴上应用缩放 CPU?
更新:
我创建 Geometry 的方式,通常使用多个立方体,但对于此示例,它只是一个实例:
const createInstancedGeometry = (instanceCount, sizeX = 1, sizeY = 1, sizeZ = 1) => {
const geometry = new InstancedBufferGeometry()
geometry.maxInstancedCount = instanceCount
const shape = new BoxBufferGeometry(0.1 * sizeX, 0.1 * sizeY, 0.1 * sizeZ)
shape.translate(0, 0.4, 0)
const data = shape.attributes
geometry.addAttribute('position', new BufferAttribute(new Float32Array(data.position.array), 3))
geometry.addAttribute('uv', new BufferAttribute(new Float32Array(data.uv.array), 2))
geometry.addAttribute('normal', new BufferAttribute(new Float32Array(data.normal.array), 3))
geometry.setIndex(new BufferAttribute(new Uint16Array(shape.index.array), 1))
shape.dispose()
createInstancedAtrributes(geometry, instanceCount)
return geometry
}
这是我设置着色器的方式,我还没有使用颜色。
const createShader = () => {
const uniforms = {
// uMap: { type: 't', value: null },
uColor1: { type: 'c', value: new Color(0x961800) }, // red
uColor2: { type: 'c', value: new Color(0x4b5828) }, // yellow
uMeshPosition: { type: 'vec3', value: new Vector3(0, 0, 0) },
}
const shader = new ShaderMaterial({
uniforms,
vertexShader,
fragmentShader,
blending: AdditiveBlending,
transparent: true,
depthWrite: false,
})
return shader
}
我的 Particle Fire 的构造函数如下所示:
constructor({ sizeX = 1, sizeY = 1, sizeZ = 1 } = {}) {
const instanceCount = 1
const geometry = createInstancedGeometry(instanceCount, sizeX, sizeY, sizeZ)
const material = createShader()
const mesh = new Mesh(geometry, material)
mesh.frustumCulled = false
this.geometry = geometry
this.material = material
this.mesh = mesh
mesh.up = new Vector3(0, 0, 1)
mesh.position.set(2, 2, 1)
mesh.rotateX(Math.PI / 2)
this.instanceCount = instanceCount
const lineGeo = new EdgesGeometry(geometry) // or WireframeGeometry
const mat = new LineBasicMaterial({ color: 0xffffff, linewidth: 2 })
const wireframe = new LineSegments(lineGeo, mat)
this.mesh.add(wireframe)
}
更新调用:
update() {
const { instanceCount } = this
const { scale, progress, randoms } = this.geometry.attributes
const { uMeshPosition } = this.material.uniforms
uMeshPosition.value = this.mesh.position
for (let i = 0; i < instanceCount; i += 1) {
let value = progress.array[i]
value += 0.025
if (value > 1) {
value -= 1
scale.setX(i, randomValueBetween(0.3, 2, 3))
// randoms.setX(i, randomValueBetween(0, 1, 3))
}
// progress.setX(i, value)
}
scale.needsUpdate = true
// randoms.needsUpdate = true
// progress.needsUpdate = true
}
我正在像这样将对象添加到场景中:
const pFire = new ParticleFire()
scene.add(pFire.mesh)
并像这样在渲染循环中更新它:
pFire.update({ deltaTime })
renderer.render(scene, cameraController.camera)
requestAnimationFrame(animate)
cameraController.camera
是一个简单的摄像机控制器,作为我在场景中移动的 'character' 的子项添加到场景中。
configuredCamera = new PerspectiveCamera(
75, window.innerWidth / window.innerHeight, 0.1, 5000,
)
THREE.Geometry
的 translate
函数平移网格的每个顶点。所以它自己的网格被置换了,它的中心不再是 (0, 0, 0)。
您应该设置 (position
) 的几何图形。参见 THREE.Object3D
。
这意味着您必须删除 shape.translate(0, 0.4, 0)
,并且必须在 geometry.position
之前完成整个放置。
然后网格不再移位,仅由 modelViewMatrix
放置。 GLS 着色器代码将起作用:
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos * scale, 1.0);
我有一个比例属性,就像我在三个 js 中应用于 instance buffered geometry 的不同实例一样。着色器看起来像这样:
attribute float scale;
uniform vec3 uMeshPosition;
void main() {
vec3 pos = position;
pos.x *= ( uMeshPosition.x - pows.x ) * scale + uMeshPosition.x;
pos.z *= ( uMeshPosition.z - pos.z ) * scale + uMeshPosition.z;
pos.y *= ( uMeshPosition.y - pos.y ) * scale + uMeshPosition.y;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1.0);
}
Z是我的身高!!!
我希望缩放的立方体保持上面线框立方体指示的初始中心。
是否可以在不计算和应用缩放的情况下在所有 3 个轴上应用缩放 CPU?
更新:
我创建 Geometry 的方式,通常使用多个立方体,但对于此示例,它只是一个实例:
const createInstancedGeometry = (instanceCount, sizeX = 1, sizeY = 1, sizeZ = 1) => {
const geometry = new InstancedBufferGeometry()
geometry.maxInstancedCount = instanceCount
const shape = new BoxBufferGeometry(0.1 * sizeX, 0.1 * sizeY, 0.1 * sizeZ)
shape.translate(0, 0.4, 0)
const data = shape.attributes
geometry.addAttribute('position', new BufferAttribute(new Float32Array(data.position.array), 3))
geometry.addAttribute('uv', new BufferAttribute(new Float32Array(data.uv.array), 2))
geometry.addAttribute('normal', new BufferAttribute(new Float32Array(data.normal.array), 3))
geometry.setIndex(new BufferAttribute(new Uint16Array(shape.index.array), 1))
shape.dispose()
createInstancedAtrributes(geometry, instanceCount)
return geometry
}
这是我设置着色器的方式,我还没有使用颜色。
const createShader = () => {
const uniforms = {
// uMap: { type: 't', value: null },
uColor1: { type: 'c', value: new Color(0x961800) }, // red
uColor2: { type: 'c', value: new Color(0x4b5828) }, // yellow
uMeshPosition: { type: 'vec3', value: new Vector3(0, 0, 0) },
}
const shader = new ShaderMaterial({
uniforms,
vertexShader,
fragmentShader,
blending: AdditiveBlending,
transparent: true,
depthWrite: false,
})
return shader
}
我的 Particle Fire 的构造函数如下所示:
constructor({ sizeX = 1, sizeY = 1, sizeZ = 1 } = {}) {
const instanceCount = 1
const geometry = createInstancedGeometry(instanceCount, sizeX, sizeY, sizeZ)
const material = createShader()
const mesh = new Mesh(geometry, material)
mesh.frustumCulled = false
this.geometry = geometry
this.material = material
this.mesh = mesh
mesh.up = new Vector3(0, 0, 1)
mesh.position.set(2, 2, 1)
mesh.rotateX(Math.PI / 2)
this.instanceCount = instanceCount
const lineGeo = new EdgesGeometry(geometry) // or WireframeGeometry
const mat = new LineBasicMaterial({ color: 0xffffff, linewidth: 2 })
const wireframe = new LineSegments(lineGeo, mat)
this.mesh.add(wireframe)
}
更新调用:
update() {
const { instanceCount } = this
const { scale, progress, randoms } = this.geometry.attributes
const { uMeshPosition } = this.material.uniforms
uMeshPosition.value = this.mesh.position
for (let i = 0; i < instanceCount; i += 1) {
let value = progress.array[i]
value += 0.025
if (value > 1) {
value -= 1
scale.setX(i, randomValueBetween(0.3, 2, 3))
// randoms.setX(i, randomValueBetween(0, 1, 3))
}
// progress.setX(i, value)
}
scale.needsUpdate = true
// randoms.needsUpdate = true
// progress.needsUpdate = true
}
我正在像这样将对象添加到场景中:
const pFire = new ParticleFire()
scene.add(pFire.mesh)
并像这样在渲染循环中更新它:
pFire.update({ deltaTime })
renderer.render(scene, cameraController.camera)
requestAnimationFrame(animate)
cameraController.camera
是一个简单的摄像机控制器,作为我在场景中移动的 'character' 的子项添加到场景中。
configuredCamera = new PerspectiveCamera(
75, window.innerWidth / window.innerHeight, 0.1, 5000,
)
THREE.Geometry
的 translate
函数平移网格的每个顶点。所以它自己的网格被置换了,它的中心不再是 (0, 0, 0)。
您应该设置 (position
) 的几何图形。参见 THREE.Object3D
。
这意味着您必须删除 shape.translate(0, 0.4, 0)
,并且必须在 geometry.position
之前完成整个放置。
然后网格不再移位,仅由 modelViewMatrix
放置。 GLS 着色器代码将起作用:
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos * scale, 1.0);