GLSL과 THREE.js로 불가능한 상자 만들기
14570 단어 glsljavascriptthreejs
최종 제품
직접 가지고 놀고 싶다면 볼 수 있습니다on my website .
더 많은 정보를 얻으려면 완전히 주석이 달린GitGub repository을 확인하십시오.
구축하자!
셰이더 및 WebGL 작동 방식의 기본 사항에 익숙하지 않은 경우 주제에 대한 이 문서MDN article를 확인하는 것이 좋습니다.
이제 제가 이것을 어떻게 구축했는지 자세히 살펴보겠습니다!
먼저 이 모든 것을 작동하게 만든 기능discard
에 대해 이야기해 보겠습니다.
프래그먼트 셰이더에는 일반 프로그래밍 언어의 return
와 유사하게 작동하는 특수 키워드가 있습니다. discard
GPU가 현재 조각을 렌더링하지 않도록 지시하여 그 뒤에 있는 것이 무엇이든 보여줍니다. 이에 대한 자세한 내용을 읽을 수 있습니다here.
이 기능을 사용하면 지루한 일반 큐브를 매우 멋진 투명 큐브로 바꿀 수 있습니다!
Source: outer_fragment.glsl
// Check if the fragment is far enough along any axis
bool x_edge = abs(worldPosition.x) > 0.4;
bool y_edge = abs(worldPosition.y) > 0.64;
bool z_edge = abs(worldPosition.z) > 0.4;
// Check that the fragment is at the edge of at least two axis'
if (!y_edge && !z_edge) {
discard;
}
if (!y_edge && !x_edge) {
discard;
}
이제 우리는 우리가 보고 있는 얼굴을 알 수 있는 방법을 찾아야 합니다. 이 부분이 가장 어려웠습니다. 해결 방법이 너무 어려워서가 아니라 대부분 제가 수학을 잘하지 못하기 때문입니다.
이제 이것을 구현하는 방법에 대해 살펴보겠습니다.
첫째, 우리 상자에는 위와 아래가 있기 때문에 이를 위해 3D로 작업할 필요가 없습니다. 3D 상자를 2D 상자로 생각해 봅시다.
이제 상자 안에 있는 3D 형상(빨간색)을 가져와서 2D로 평면화할 수 있습니다.
다음으로 카메라(파란색)와 렌더링하려는 일부 예제 조각(녹색)을 추가해 보겠습니다.
이 설정을 사용하면 프래그먼트와 카메라 사이에 선을 만들고 어떤 면을 통과하는지 확인할 수 있습니다.
이 방법을 상자에 적용하고 각 얼굴에 색상을 지정하면 재미있는 효과를 얻을 수 있습니다!
Source: inner_fragment.glsl
// Define all the corners of our box
const vec2 corners[4] = vec2[](vec2(0.5, 0.5), vec2(-0.5, 0.5), vec2(-0.5, -0.5), vec2(0.5, -0.5));
// Define a line from the fragment's position (A) to the camera (B)
vec2 a = worldPosition.xz;
vec2 b = cameraPosition.xz;
int intersectedFace = -1;
// Iterate over each face
for (int i = 0; i < 4; i++) {
// Get the second point for our face
int next = int(mod(float(i + 1), 4.0));
// Create a line from 2 corners based on the face
vec2 c = corners[i];
vec2 d = corners[next];
// Does line 1 and 2 intersect? If so, assign the intersected face
if (intersect(a, b, c, d)) {
intersectedFace = i;
break;
}
}
// Color the fragment based on the face
switch (intersectedFace) {
case -1:
gl_FragColor = vec4(1, 0, 1, 1);
break;
case 0:
gl_FragColor = vec4(1, 0, 0, 1);
break;
case 1:
gl_FragColor = vec4(0, 1, 0, 1);
break;
case 2:
gl_FragColor = vec4(0, 0, 1, 1);
break;
case 3:
gl_FragColor = vec4(0, 1, 1, 1);
break;
}
여기에서 내부에 원하는 각 개체에 얼굴을 할당하고 지정된 얼굴을 통과하지 않는 조각discard
을 할당할 수 있습니다.
Source: inner_fragment.glsl
// Define a line from the fragment's position (A) to the camera (B)
vec2 a = worldPosition.xz;
vec2 b = cameraPosition.xz;
// Get the second point to define the face
int next = int(mod(float(face + 1), 4.0));
// Define a line at the given face
vec2 c = corners[face];
vec2 d = corners[next];
// If the defined lines do NOT intersect, then discard the fragment
if (!intersect(a, b, c, d)) {
discard;
}
그런 다음 몇 가지 흥미로운 애니메이션 개체, 깊이를 위한 약간의 방향성 조명을 추가하면 완료됩니다!
읽어 주셔서 감사합니다! 제가 만든 만큼 즐거우셨기를 바랍니다!
Reference
이 문제에 관하여(GLSL과 THREE.js로 불가능한 상자 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/jessesolomon/creating-an-impossible-box-with-glsl-three-js-3mi5
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
셰이더 및 WebGL 작동 방식의 기본 사항에 익숙하지 않은 경우 주제에 대한 이 문서MDN article를 확인하는 것이 좋습니다.
이제 제가 이것을 어떻게 구축했는지 자세히 살펴보겠습니다!
먼저 이 모든 것을 작동하게 만든 기능
discard
에 대해 이야기해 보겠습니다.프래그먼트 셰이더에는 일반 프로그래밍 언어의
return
와 유사하게 작동하는 특수 키워드가 있습니다. discard
GPU가 현재 조각을 렌더링하지 않도록 지시하여 그 뒤에 있는 것이 무엇이든 보여줍니다. 이에 대한 자세한 내용을 읽을 수 있습니다here.이 기능을 사용하면 지루한 일반 큐브를 매우 멋진 투명 큐브로 바꿀 수 있습니다!
Source: outer_fragment.glsl
// Check if the fragment is far enough along any axis
bool x_edge = abs(worldPosition.x) > 0.4;
bool y_edge = abs(worldPosition.y) > 0.64;
bool z_edge = abs(worldPosition.z) > 0.4;
// Check that the fragment is at the edge of at least two axis'
if (!y_edge && !z_edge) {
discard;
}
if (!y_edge && !x_edge) {
discard;
}
이제 우리는 우리가 보고 있는 얼굴을 알 수 있는 방법을 찾아야 합니다. 이 부분이 가장 어려웠습니다. 해결 방법이 너무 어려워서가 아니라 대부분 제가 수학을 잘하지 못하기 때문입니다.
이제 이것을 구현하는 방법에 대해 살펴보겠습니다.
첫째, 우리 상자에는 위와 아래가 있기 때문에 이를 위해 3D로 작업할 필요가 없습니다. 3D 상자를 2D 상자로 생각해 봅시다.
이제 상자 안에 있는 3D 형상(빨간색)을 가져와서 2D로 평면화할 수 있습니다.
다음으로 카메라(파란색)와 렌더링하려는 일부 예제 조각(녹색)을 추가해 보겠습니다.
이 설정을 사용하면 프래그먼트와 카메라 사이에 선을 만들고 어떤 면을 통과하는지 확인할 수 있습니다.
이 방법을 상자에 적용하고 각 얼굴에 색상을 지정하면 재미있는 효과를 얻을 수 있습니다!
Source: inner_fragment.glsl
// Define all the corners of our box
const vec2 corners[4] = vec2[](vec2(0.5, 0.5), vec2(-0.5, 0.5), vec2(-0.5, -0.5), vec2(0.5, -0.5));
// Define a line from the fragment's position (A) to the camera (B)
vec2 a = worldPosition.xz;
vec2 b = cameraPosition.xz;
int intersectedFace = -1;
// Iterate over each face
for (int i = 0; i < 4; i++) {
// Get the second point for our face
int next = int(mod(float(i + 1), 4.0));
// Create a line from 2 corners based on the face
vec2 c = corners[i];
vec2 d = corners[next];
// Does line 1 and 2 intersect? If so, assign the intersected face
if (intersect(a, b, c, d)) {
intersectedFace = i;
break;
}
}
// Color the fragment based on the face
switch (intersectedFace) {
case -1:
gl_FragColor = vec4(1, 0, 1, 1);
break;
case 0:
gl_FragColor = vec4(1, 0, 0, 1);
break;
case 1:
gl_FragColor = vec4(0, 1, 0, 1);
break;
case 2:
gl_FragColor = vec4(0, 0, 1, 1);
break;
case 3:
gl_FragColor = vec4(0, 1, 1, 1);
break;
}
여기에서 내부에 원하는 각 개체에 얼굴을 할당하고 지정된 얼굴을 통과하지 않는 조각
discard
을 할당할 수 있습니다.Source: inner_fragment.glsl
// Define a line from the fragment's position (A) to the camera (B)
vec2 a = worldPosition.xz;
vec2 b = cameraPosition.xz;
// Get the second point to define the face
int next = int(mod(float(face + 1), 4.0));
// Define a line at the given face
vec2 c = corners[face];
vec2 d = corners[next];
// If the defined lines do NOT intersect, then discard the fragment
if (!intersect(a, b, c, d)) {
discard;
}
그런 다음 몇 가지 흥미로운 애니메이션 개체, 깊이를 위한 약간의 방향성 조명을 추가하면 완료됩니다!
읽어 주셔서 감사합니다! 제가 만든 만큼 즐거우셨기를 바랍니다!
Reference
이 문제에 관하여(GLSL과 THREE.js로 불가능한 상자 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/jessesolomon/creating-an-impossible-box-with-glsl-three-js-3mi5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)