티스토리 뷰

42/cub3d

cub3d - wall

stdbc 2020. 10. 15. 02:56

로데브 中 텍스쳐를 이해하는 페이지.

 

이해했던 흐름 그대로의 정리라서 로데브 원본과 살짝 차이가 있습니다.

 

1. 벽 텍스쳐 (affine texture mapping)

2. 천장, 바닥 텍스쳐

3. 텍스쳐에 투명도 넣기


1. 벽 텍스쳐 (affine texture mapping)

 

광선으로 벽의 높이를 구한 다음부터의 내용

int texNum = worldMap[mapX][mapY] - 1;

double obj_x = (ray.side == 0) ? posY + perpWallDist * rayDirY : posX + perpWallDist * rayDistX; 

int img_x = (int)(img_width * (obj_x - floor(obj_x))); 
if (wall->type == SOUTH || wall->type == WEST)
    img_x = img_width - img_x - 1;

double obj_y = 0;
if (draw_start == 0)
    obj_y = wall_height / 2 - win_h / 2;

y = draw_start;
while (y < draw_end)
{
    int img_y = (int)(img_height * obj_y / wall_height);
    int tex_point = size_l / (bpp / 8) * img_y + img_x;
    buf[y][x] = data[texNum][tex_point];
    obj_y++;
    y++;
}    

 

전체적인 흐름은 x좌표를 잡은 상태에서 수직으로 내려오면서 텍스쳐(이미지)를 가져오는 것이다.

obj_x: 벽에 부딪혔을 때 가로 좌표
obj_y: 그 위치에서 수직으로 올린 벽 시작점

(img_x, img_y): 그 때 텍스쳐에 해당하는 위치
img_height, img_width: 텍스쳐 각각의 가로세로 (각 텍스쳐 크기가 다른 경우 위 코드에서 보완 필요)

 

 

예시를 보면서 이해해보자.

왼쪽 벽에 오른쪽 4 * 2 사이즈의 텍스쳐를 넣을 것이다.

 

 

가로 과정

 

1. 광선이 벽에 부딪혔을 때 x 좌표를 구한다. (왼쪽 갈색별) (값은 레이캐스팅 과정에서 구해진다.)
      ex) obj_x = 44.23


2. 벽 가로에 대한 obj_x의 상대적 위치를 구한다. 가로가 1이기 때문에 정수부분을 빼서 소수부분으로 상대적 위치를 구할 수 있다.
      ex) obj_x - floor(obj_x) = 44.23 - 44 = 0.23


3. 상대적 위치를 원본 텍스쳐 width에 적용한다.
      ex) img_x = (int)(4 * 0.23) = (int) (0.92) = 0
      
      
4. [img_x = 0]이 실제 텍스쳐에서 가져올 가로 위치. (오른쪽 갈색별 위치를 int로 변환)

 

 

세로 과정

 

 

wall_height = 64라고 가정하자 (실제 구현에서는 texture 단계 이전에 wall_height를 구하는 과정이 있다.)


1. obj_x에서 수직으로 올라와 벽 시작점 obj_y를 잡는다. (왼쪽 파란별)
   (일단 스크린에 벽 전체가 보일 경우로 가정했다. 이때 obj_y는 0이다)
    ex) obj_y = 0


2. 벽 세로에 대한 obj_y의 상대적 위치를 구한다. 내 위치를 벽 높이로 나눠주면 상대적 위치를 구할 수 있다.
    ex) obj_y / 64 = 0


3. 상대적 위치를 원본 텍스쳐 height에 적용한다.
   ex) img_y = (int)(2 * 0) = 0
   
   
4. [img_y = 0]이 실제 텍스쳐에서 가져올 세로 위치. (오른쪽 흰색별 위치를 int로 변환)

 

종합하면 [img_x = 0, img_y = 0]으로 파란색 픽셀을 가져오게 된다.

 

 

while문을 계속 돌아서 obj_y = 40이 되었다면

1. obj_y = 40

2. obj_y의 상대적 위치는 40 / 64 = 5 / 8

3. pos_y = (int) (2 * 5 / 8) = 1

[img_x = 0, img_y = 1]으로 흰색 픽셀을 가져온다.

 


스킵했던 부분 설명

1.
img_x = (int)(img_width * (obj_x - floor(obj_x)); 
if (wall->type == SOUTH || wall->type == WEST)
    img_x = img_width - img_x - 1;
  
  
2.
obj_y = 0;
if (draw_start == 0)
    obj_y = wall_height / 2 - win_h / 2;

 

1.

스크린을 띄워보면 벽면이 가로로 뒤집혀서 그려지는 방향이 있다. (대칭이 아닌 텍스쳐를 넣어보면 바로 눈에 보인다.)

[img_x = img_width - img_x - 1] 이 찍은 위치를 다시 뒤집어서 정상적으로 돌려주는 부분이다.

 

(side == 0 && rayDirX > 0) || (side == 1 && rayDirY < 0) 조건문을 그대로 써도 되고, cub3d 과제 내용 중 방향을 정하는 부분이 있기 때문에 위 코드처럼 단순화할 수도 있다.

 

 

2.

[obj_y= 0]은 벽 높이가 스크린 높이보다 작아서 화면에 벽 전체가 그려지는 경우를 가정한 것이었다. (멀리서 벽을 바라볼 때)

 

하지만 아래 그림처럼 벽 높이가 노란색 스크린보다 커지는 경우가 있다. (벽 바로 앞에 섰을 때)

 

texture 이전 단계에서 이런 경우를 draw_start = 0, draw_end = win_height로 보정해주었다.

마찬가지로 보정이 필요한데, 이때는 벽 제일 윗부분을 시작점(obj_y = 0)으로 잡으면 안되고, 화면에 그려주는 부분부터 시작해야 한다.

그 시작점이 벽 절반 높이에서 화면 절반 높이를 뺀 위치다.

 

그래서 draw_start == 0일 땐 [obj_y = wall_height / 2 - win_height / 2]

 


마지막으로, 구한 텍스쳐 위치(img_x, img_y)로 데이터에서 색상을 가져와서 버퍼에 넣어준다.

텍스쳐 위치로 색상을 가져오는 계산은 mlx_get_data_addr 페이지에 설명되어 있다.

tex_point = size_l / (bpp / 8) * img_y + img_x;
buf[y][x] = data[tex_point];

 

 

x 하나에 대해서 수직으로 전부 내려오면 아래처럼 저장되고

이 작업을 모든 x에 대해(스크린 widht만큼) 실행하면 버퍼에 화면 전체 벽이 저장된다.

 

 

'42 > cub3d' 카테고리의 다른 글

cub3d - 완성본  (0) 2020.10.19
cub3d - lodev 레이캐스팅, 카메라행렬  (0) 2020.10.19
cub3d - transparency  (0) 2020.10.17
cub3d - mlx_get_data_addr  (0) 2020.09.23
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함