Hello, I would like to inquire again.
In the first photo, the rising line is rendered as if it were inside a circle.
However, in the case of the second photo, when you turn the camera viewpoint, the line rises and is like a circle.
What part can I fix?
Please help me.
Below is my code for rendering a line and a circle.
thank you.
let lineAnimateTime;
let isShot = false;
let trajectoryIteration = 2;
let previousLine;
let previousShadowLine;
function setupLine() {
// Animation Sensor Time
const PERSPECTIVE_LAYER = 2;
const PATH_SEGMENTS = 32;
const LINE_THICKNESS = 0.4;
const SHADER_THICKNESS = 0.4;
const Roundness = 12;
const IS_Closed = false;
const LINE_Y_POSITION = -20;
const linePoints = [new THREE.Vector3(0, 0, 0).multiplyScalar(1)];
const shaderPoints = [new THREE.Vector3(0, 0, 0).multiplyScalar(1)];
const lineMaterial = new THREE.ShaderMaterial({
uniforms: {
color: { value: new THREE.Color("red") },
maxZ: { value: 0.0 },
minZ: { value: 0.0 }
},
vertexShader: `
uniform float maxZ;
uniform float minZ;
varying float alpha;
void main() {
float range = maxZ - minZ;
alpha = smoothstep(0.7, 1.0, (abs(position.z - minZ) / range));
alpha = min(alpha, 0.7); // 최대 0.7까지 제한
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform vec3 color;
varying float alpha;
void main() {
gl_FragColor = vec4(color, 1.0 - alpha); // 처음이 밝고 뒷부분이 어둡게
}
`,
transparent: true,
depthTest: true, // 선이 다른 객체를 가리지 않도록 depthTest를 비활성화
});
const shaderLineMaterial = new THREE.ShaderMaterial({
uniforms: {
color: { value: new THREE.Color("black") },
maxZ: { value: 0.0 },
minZ: { value: 0.0 }
},
vertexShader: `
uniform float maxZ;
uniform float minZ;
varying float alpha;
void main() {
float range = maxZ - minZ;
alpha = smoothstep(0.7, 1.0, (abs(position.z - minZ) / range));
alpha = min(alpha, 0.7); // 최대 0.7까지 제한
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform vec3 color;
varying float alpha;
void main() {
gl_FragColor = vec4(color, 1.0 - alpha); // 처음이 밝고 뒷부분이 어둡게
}
`,
transparent: true,
depthTest: true,
});
if (trajectoryIteration < trajectory.length) {
if(lineAnimateTime + 0.02 < clock.getElapsedTime()) {
lineAnimateTime = clock.getElapsedTime();
for (let i = 1; i < trajectoryIteration; i++) {
linePoints.push( new THREE.Vector3(trajectory[i].x, trajectory[i].z, -trajectory[i].y).multiplyScalar(1));
shaderPoints.push( new THREE.Vector3(trajectory[i].x, 0, -trajectory[i].y).multiplyScalar(1));
}
let isXWithinXBounds = trajectory[trajectoryIteration].x >= targetCircle.position.x - targetRadius && trajectory[trajectoryIteration].x <= targetCircle.position.x + targetRadius;
let isZWithinZBounds = trajectory[trajectoryIteration].y >= Math.abs(targetCircle.position.z) - targetRadius && trajectory[trajectoryIteration].y <= Math.abs(targetCircle.position.z) + targetRadius;
if(isXWithinXBounds && isZWithinZBounds) {
// shadowCircle.material.color.set('blue');
} else {
// shadowCircle.material.color.set('red');
}
const maxZ = Math.max(...linePoints.map(point => point.z));
const minZ = Math.min(...linePoints.map(point => point.z));
lineMaterial.uniforms.maxZ = { value: maxZ };
lineMaterial.uniforms.minZ = { value: minZ };
const tubeGeometry = new THREE.TubeGeometry(
new THREE.CatmullRomCurve3(linePoints),
PATH_SEGMENTS,
LINE_THICKNESS,
Roundness,
IS_Closed
);
const shaderTubeGeometry = new THREE.TubeGeometry(
new THREE.CatmullRomCurve3(shaderPoints),
PATH_SEGMENTS,
SHADER_THICKNESS,
Roundness,
IS_Closed
);
scene2.remove(previousLine);
scene2.remove(previousShadowLine);
const line = new THREE.Mesh(shaderTubeGeometry, shaderLineMaterial);
const shadowLine = new THREE.Mesh(tubeGeometry, lineMaterial);
previousLine = line;
previousShadowLine = shadowLine;
line.layers.set(PERSPECTIVE_LAYER);
shadowLine.layers.set(PERSPECTIVE_LAYER);
line.position.y = LINE_Y_POSITION;
shadowLine.position.y = LINE_Y_POSITION;
renderer.setTransparentSort((a , b) => {
return 1;
})
scene2.add(line)
line.renderOrder = 1;
scene2.add(shadowLine);
trajectoryIteration++;
}
} else {
setTimeout(() => {
// shadowCircle.material.color.set('white');
}, 1000)
isShot = false;
trajectoryIteration = 2;
trajectory = [];
}
}
function setupTarget(radius, thickness, numRectangles, distance) {
const circle = new THREE.Group();
const circle2 = new THREE.Group();
const borderMaterial = new THREE.MeshBasicMaterial({
color: 0xffdd00, // Set color as needed
side: THREE.DoubleSide, // Render on the back side
transparent: true,
opacity: 0.9,
});
const borderMaterial2 = new THREE.MeshBasicMaterial({
color: 0xffffff, // Set color as needed
side: THREE.DoubleSide, // Render on the back side
transparent: true,
opacity: 0.9,
});
for (let i = 0; i < numRectangles; i+=radius / 4) {
const angle = (i / numRectangles) * Math.PI * 2;
const rectangle = new THREE.Mesh(
new THREE.BoxGeometry(1, 3, 0.5),
borderMaterial
);
const rectangle2 = new THREE.Mesh(
new THREE.BoxGeometry(1, 3, 0.5),
borderMaterial2
);
// Set position in a circle
rectangle.position.x = radius * Math.cos(angle);
rectangle.position.y = radius * Math.sin(angle);
rectangle.rotation.z = angle;
rectangle.layers.set(2);
rectangle2.position.x = radius * Math.cos(angle);
rectangle2.position.y = radius * Math.sin(angle);
rectangle2.rotation.z = angle;
rectangle2.layers.set(2);
circle.add(rectangle);
circle2.add(rectangle2);
}
circle.position.z = DEFAULT_Z_AXIS_VALUE - distance;
circle2.position.z = DEFAULT_Z_AXIS_VALUE - distance;
circle.rotateX(-Math.PI / 2);
circle.position.y = -20;
circle2.position.y = -16;
circle2.rotateX(-Math.PI / 2);
circle2.renderOrder = 4;
circle.renderOrder = 4;
const f1 = gui.addFolder('Target Controls');
f1.add(circle.position, 'z', -1000, 1000);
f1.add(circle.position, 'y', -1000, 1000);
scene2.add(circle);
scene2.add(circle2);
return {targetCircle : circle, shadowCircle : circle2};
};