상세 컨텐츠

본문 제목

SCOP: 자연스러운 텍스처 매핑을 위한 UV 좌표계 경계 처리 - (8)

Computer Graphics/SCOP

by Banjosh 2024. 10. 1. 15:48

본문

 이번에는 오브젝트의 정점 좌표를 UV 좌표계로 변환하여 텍스처를 적용해보았다. 이를 위해 다음과 같은 코드를 추가하여 렌더링을 진행했다.

    for (int i = 0; i < vertices.size(); i = i + 3) {
    	for (int j = 0; j < 3; j++) {
            glmath::vec3 pos = vertices[i + j].pos;
            float r = std::sqrt(pos.x * pos.x + pos.y * pos.y + pos.z * pos.z);
            if (r == 0) r = 0.01f;
            float theta = std::atan2(pos.z, pos.x);
            float phi = std::asin(pos.y / r);
            float U = (phi + glmath::pi / 2) / glmath::pi * colPattern;
            float V = (theta + glmath::pi) / (2 * glmath::pi) * rowPattern;
            vertices[i + j].texCoord.x = V;
            vertices[i + j].texCoord.y = U;
        }
    }

 


하지만, 렌더링 결과를 확인해보니 특정 부분에서 텍스처가 불규칙적으로 반복되는 현상이 발생했다.

 

 

문제 원인

문제는 삼각형의 정점 중 일부가 UV 좌표계의 경계를 넘어가는 위치에 있을 때 발생했다. 예를 들어, 삼각형의 정점 3개 중 하나의 θ(theta)가 1.9π, 다른 하나는 -0.1π인 경우, 실제 값 차이는 0.2π에 불과하지만, UV 좌표계는 0 ~ 2π로 제한되어 있으므로 두 좌표 간의 차이를 큰 값으로 인식하게 된다. 그 결과 텍스처가 경계에서 왜곡되며 잘못된 패턴으로 렌더링되었다.

해결 방법

이 문제를 해결하기 위해, UV 좌표가 경계를 넘어가는지 확인하는 함수를 추가했다. 만약 경계를 넘어간다면, 그 좌표에 2π를 더해줌으로써 자연스러운 텍스처 적용이 가능하게 수정했다.

아래는 수정된 코드이다.

 

bool Model::isAcrossUVBoundary(std::vector<Vertex>& vertices, int idx) {

	bool startAria = false;
	bool endAria = false;

	for (int i = 0; i < 3; i++) {
		if (vertices[idx + i].pos.x <= 0 && vertices[idx + i].pos.z >= 0) {
			startAria = true;
		}
		if (vertices[idx + i].pos.x <= 0 && vertices[idx + i].pos.z < 0) {
			endAria = true;
		}
	}
	return (startAria && endAria);
}

void Model::makeTextureCoord(std::vector<Vertex>& vertices) {
	float rowPattern = 8;
	float colPattern = 8;
	
	for (int i = 0; i < vertices.size(); i = i + 3) {
		for (int j = 0; j < 3; j++) {
			glmath::vec3 pos = vertices[i + j].pos - m_modelPos;

			float r = std::sqrt(pos.x * pos.x + pos.y * pos.y + pos.z * pos.z);
			if (r == 0) r = 0.01f;
			float theta = std::atan2(pos.z, pos.x);
			float phi = std::asin(pos.y / r);
			float U = (phi + glmath::pi / 2) / glmath::pi * colPattern;
			float V = (theta + glmath::pi) / (2 * glmath::pi) * rowPattern;
			vertices[i + j].texCoord.x = V;
			vertices[i + j].texCoord.y = U;
		}
		if (isAcrossUVBoundary(vertices, i)) {
			for (int j = 0; j < 3; j++) {
				if (vertices[i + j].texCoord.x < rowPattern / 2) {
					vertices[i + j].texCoord.x += rowPattern;
				}
			}
		}
	}
}

 

개선 사항

추가적으로, rowPatterncolPattern 변수를 사용하여 텍스처가 단일 패턴으로만 적용되지 않고, 여러 번 반복되어 적용되도록 설정했다. 이는 텍스처가 더욱 자연스럽게 오브젝트에 입혀지도록 하기 위함이다.

이렇게 수정된 코드로 렌더링한 결과, 이전보다 훨씬 자연스럽게 텍스처가 적용되는 것을 확인할 수 있었다

 

 

이렇게 수정된 코드로 렌더링한 결과, 이전보다 훨씬 자연스럽게 텍스처가 적용되는 것을 확인할 수 있었다.

 


이번 작업을 통해 텍스처가 UV 좌표계의 경계 문제로 인해 왜곡되는 문제를 해결하면서 텍스처 매핑에 대한 이해도를 높일 수 있었다.

관련글 더보기