.☝ PROCEDURAL은 절차적인 의미로써 모델링 또는 fx에서 많이 쓰인다.
프로시졀의 장점은 예측이 가능하고, 특정 부분에서 런타임중 접근이 용이하다.
일반적으로 모델러가 만들어준 모델링은 그 과정을 알 수가 어렵기 때문에 항상 결과물만 이용하게 된다.
하지만, 프로시졀 모델링은 그 과정을 알 수 있기 때문에 수정이 용이하다
대표적으로 프로시졀 모델링은 후디니에서 많이 사용한다. (노드 기반)
-----
저번에 이어서 면을 만들어 줄 것인데
이번에는 점을 가지고 있는 플랜한 면을 만들어 줄 것이다.
기본적인 오브젝트를 하나 만들어주고,
메시 필터, 메시 렌더러, 만들어준 스크립터를 달아준다.
using UnityEngine;
public class MeshGenerate : MonoBehaviour
{
Mesh mesh;
Vector3[] vertices;
int[] triangles;
[SerializeField]
public int xSize = 20, zSize = 20;
void Start()
{
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
CreateShape();
UpdateMesh();
}
private void CreateShape()
{
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
vertices[i] = new Vector3(x, 0, z);
i++;
}
}
}
private void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
}
private void OnDrawGizmos()
{
if (vertices == null) return;
for (int i = 0; i < vertices.Length; i++)
{
Gizmos.DrawSphere(vertices[i], 0.1f);
}
}
}
먼저 변수쪽을 보면
Mesh mesh;
Vector3[] vertices;
int[] triangles;
[SerializeField]
public int xSize = 20, zSize = 20;
mesh 는 만들어줄 면을 뜻하고
Vec3 배열은 만들어줄 점들의 배열
int 배열은 면을 만들어줄 정점의 포인트 지점
xSize와 zSize 는
만들어줄 플랜의 x개수, z 개수를 뜻한다.
---
void Start()
{
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
CreateShape();
UpdateMesh();
}
처음에
새로운 mesh를 만들어주고,
현재 컴포넌트에 있는 메시필터에 만들어준 mesh를 넣어준다.
CreateShape 와 UpdateMesh 메서드를 호출 해준다.
---
private void CreateShape()
{
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
vertices[i] = new Vector3(x, 0, z);
i++;
}
}
}
CreateShape를 보면
xSize와 zSize로 정점을 만들어준다.
0 지점 때문에 +1 한 개수로 총 정점에 대한 배열 사이즈를 지정해준다.
이중배열로 z for를 돌리고, x for를 돌려준다.
0지점부터 만들어주기 때문에 <= 를 달아줘야한다.
i 는 총 점의 갯수의 인덱스 값임
z 인덱스가 0 일때
vertices[0] = new Vector3(0, 0, 0);
vertices[1] = new Vector3(1, 0, 0);
vertices[2] = new Vector3(2, 0, 0);
..... 쭉쭉 생성이 되고,
x값 만큼 다 돌면
z인덱스가 1이 된다
vertices[21] = new Vector3(0, 0, 1);
vertices[22] = new Vector3(1, 0, 1);
vertices[23] = new Vector3(2, 0, 1);
쭉쭉 생성이 된다.
----
private void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
}
private void OnDrawGizmos()
{
if (vertices == null) return;
for (int i = 0; i < vertices.Length; i++)
{
Gizmos.DrawSphere(vertices[i], 0.1f);
}
}
업데이트 메서드에서는
위에서 만들어준 배열 값을 최신화 시켜주는 역할을한다.
그리고 정점을 보기 위해서
OnDrawGizmos 로 정점 길이와, 값을 가져와서 그려준다.
-----
플레이 해주면 20x20 정점이 만들어진다.
---
이제 면을 채워줄 것이다.
private void CreateShape()
{
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
vertices[i] = new Vector3(x, 0, z);
i++;
}
}
triangles = new int[3];
triangles[0] = 0;
triangles[1] = xSize + 1;
triangles[2] = 1;
}
CreateShape 메서드에
triangles = new int[3];
triangles[0] = 0;
triangles[1] = xSize + 1;
triangles[2] = 1;
정점에 대한 인트 값을 넣어준다.
점을 그려주는 데, 정점에 대한 인트 값은
반 시계 방향으로 그려준다.
1번 째는 0
2번 째는 총 x 사이즈의 +1 인 -> 4가 되고
3번째는 1이 된다.
플레이를 하게되면 정상적으로 삼각형 면 하나가 만들어진다.
triangles = new int[6];
triangles[0] = 0;
triangles[1] = xSize + 1;
triangles[2] = 1;
triangles[3] = 1;
triangles[4] = xSize + 1;
triangles[5] = xSize + 2;
나머지 면을 그려주려면
이런 방식이기 때문에
triangles[3] = 1;
triangles[4] = xSize + 1;
triangles[5] = xSize + 2;
정점을 추가시켜준다.
정상적으로 한개의 면이 만들어진다.
이걸 이제 for를 돌리면서 여러개 생성을 해준다.
private void CreateShape()
{
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
vertices[i] = new Vector3(x, 0, z);
i++;
}
}
triangles = new int[xSize * zSize * 6];
int vert = 0;
int tris = 0;
for (int x = 0; x < xSize; x++)
{
triangles[tris + 0] = vert + 0;
triangles[tris + 1] = vert + xSize + 1;
triangles[tris + 2] = vert + 1;
triangles[tris + 3] = vert + 1;
triangles[tris + 4] = vert + xSize + 1;
triangles[tris + 5] = vert + xSize + 2;
vert++;
tris += 6;
}
}
triangles = new int[xSize * zSize * 6];
int vert = 0;
int tris = 0;
for (int x = 0; x < xSize; x++)
{
triangles[tris + 0] = vert + 0;
triangles[tris + 1] = vert + xSize + 1;
triangles[tris + 2] = vert + 1;
triangles[tris + 3] = vert + 1;
triangles[tris + 4] = vert + xSize + 1;
triangles[tris + 5] = vert + xSize + 2;
vert++;
tris += 6;
}
우선 triangles의 정점 총 갯수는
xSize와 zSize와 한면을 만들기 위한 6개 정점을 모두 곱한 값임
xSize * zSize * 6 를 해줌
int vert 와 tris 인덱스를 변수로 만들어주고,
먼저 xSize에 대한 for 를 만들어준다.
triangles[tris + 0] 에 tris 값으로 인덱서를 해준다.
한 면을 만드는 사이클이 6이기 때문에
for 마지막에서 += 6; 연산을 해주기 때문에
triangles에 인덱서는 for를 돌 때마다 새로운 정점을 지정하게 됨.
vert는 1씩 증가하여 1씩 증가된 값을 가지게 한다.
한 개 삼각형을 그릴때 이런식으로 작동함
플레이하면 xSize에 대한 면이 만들어진다.
이제 zSize 값만큼 이중 포문으로 해주면 나머지 면도 추가해준다.
private void CreateShape()
{
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
vertices[i] = new Vector3(x, 0, z);
i++;
}
}
triangles = new int[xSize * zSize * 6];
int vert = 0;
int tris = 0;
for (int z = 0; z < zSize; z++)
{
for (int x = 0; x < xSize; x++)
{
triangles[tris + 0] = vert + 0;
triangles[tris + 1] = vert + xSize + 1;
triangles[tris + 2] = vert + 1;
triangles[tris + 3] = vert + 1;
triangles[tris + 4] = vert + xSize + 1;
triangles[tris + 5] = vert + xSize + 2;
vert++;
tris += 6;
}
vert++;
}
}
triangles = new int[xSize * zSize * 6];
int vert = 0;
int tris = 0;
for (int z = 0; z < zSize; z++)
{
for (int x = 0; x < xSize; x++)
{
triangles[tris + 0] = vert + 0;
triangles[tris + 1] = vert + xSize + 1;
triangles[tris + 2] = vert + 1;
triangles[tris + 3] = vert + 1;
triangles[tris + 4] = vert + xSize + 1;
triangles[tris + 5] = vert + xSize + 2;
vert++;
tris += 6;
}
vert++;
}
z 이중 포문으로 해주고,
x 한번 다 돌면
vert++를 해줘야지 다음 위 칸에 대한 vert 계산을 하기 댸문에
z 포문 안에 vert++;를 해준다 .
이런 플랜을 만들 수 있음
추가적으로 버텍스의 y 값을 노이즈맵으로 높이 값을 줄 수 있음
private void CreateShape()
{
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
float y = Mathf.PerlinNoise(x * 0.3f, z * 0.3f) * 2f;
vertices[i] = new Vector3(x, y, z);
i++;
}
}
triangles = new int[xSize * zSize * 6];
int vert = 0;
int tris = 0;
for (int z = 0; z < zSize; z++)
{
for (int x = 0; x < xSize; x++)
{
triangles[tris + 0] = vert + 0;
triangles[tris + 1] = vert + xSize + 1;
triangles[tris + 2] = vert + 1;
triangles[tris + 3] = vert + 1;
triangles[tris + 4] = vert + xSize + 1;
triangles[tris + 5] = vert + xSize + 2;
vert++;
tris += 6;
}
vert++;
}
}
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
float y = Mathf.PerlinNoise(x * 0.3f, z * 0.3f) * 2f;
vertices[i] = new Vector3(x, y, z);
i++;
}
}
버텍스를 만들어주는 for문에서
y 값을 PerlinNoise 값을 사용해준다.
[PerlinNoise] 관련
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=daehuck&logNo=220457203383
y 값을 PerlinNoise 값을 이용해서 넣어주면
이러한 노이즈맵이 만들어진다.
------
메쉬는 결국 정점이 모여서 면이 만들어 지는 것!
정점을 잘 이용하면 재미있는 것들이 가능 할 듯!
굳 .👍
'Unity > 그래픽스프로그래밍' 카테고리의 다른 글
Unity Mesh Create Basic _ 유니티 면 만들기 기본 (0) | 2022.09.18 |
---|---|
210715_ 그래픽스 프로그래밍(복습 및 시험) (0) | 2021.07.15 |
0510_ 알파 테스트와 컷 아웃 (0) | 2021.05.10 |
0507 _ 큐브맵 만들어서, 물체에 월드 노멀, 리플렉션 적용시기키 (0) | 2021.05.07 |
0507_Diffuse Warping 만들어보기 (0) | 2021.05.07 |