Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Complete korean translation of tutorial 4. #93

Open
wants to merge 2 commits into
base: gh-pages
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 48 additions & 48 deletions kr/beginners-tutorials/tutorial-4-a-colored-cube/index.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ language: kr

# 육면체 그리기

하나의 육면체는 6개의 사각 면으로 되어 있습니다. OpenGL은 삼각형만 처리 할 수 있기 때문에, 우리는 12개의 삼각형을 그려야 합니다. 사각면 하나 당 2개의 삼각형이 필요합니다. 삼각형을 그릴 때와 같은 방법으로 Vertex들을 정의합니다.
하나의 육면체는 6개의 사각형으로 되어 있습니다. OpenGL은 삼각형만 처리할 수 있기 때문에, 우리는 12개의 삼각형을 그려야 합니다. 사각면 하나 당 2개의 삼각형이 필요합니다. 삼각형을 그릴 때와 같은 방법으로 Vertex들을 정의합니다.

``` cpp
// 우리 Vertex들입니다. 3개의 연속 된 float 숫자가 하나의 3차원 Vertex입니다.
Expand Down Expand Up @@ -67,7 +67,7 @@ static const GLfloat g_vertex_buffer_data[] = {
};
```

OpenGL 버퍼는 표준 함수들을(glGenBuffers, glBindBuffer, glBufferData, glVertexAttribPointer) 이용해서 생성되고, 연결되고(bound), 채워지고, 설정 됩니다. 잠시 Tutorial 2를 복습 겸 살펴보셔도 좋겠습니다. draw call(억지로 한글로 번역하면 이상해서 그냥 draw call 그대로 사용)도 같습니다. 그냥 그려져야 할 정확한 Vertex의 개수만 설정 해 주면 됩니다.:
OpenGL 버퍼는 표준 함수들을(glGenBuffers, glBindBuffer, glBufferData, glVertexAttribPointer) 이용해서 생성되고, 연결되고(bound), 채워지고, 설정됩니다. 잠시 Tutorial 2를 복습 겸 살펴보셔도 좋습니다. draw call도 같습니다. 그냥 그려져야 할 정확한 Vertex의 개수만 설정 해 주면 됩니다.:

``` cpp
// 삼각형 그리기
Expand All @@ -76,19 +76,19 @@ glDrawArrays(GL_TRIANGLES, 0, 12*3); // 12*3 indices starting at 0 -> 12 triangl

이 코드에서 주목 할 몇 가지 :

* 지금은 우리 3D 모델이 고정되어 있습니다. 모델을 수정하려면 소스 코드를 고치고 다시 어플리케이션을 컴파일하고~~ 잘 되길 바래야 합니다.^^ Tutorial 7에서 동적인 모델을 로딩 하는 방법을 배우게 됩니다.
* 실제로는 각 Vertex가 적어도 3번 적혀 있습니다.("-1.0f,-1.0f,-1.0f"을 위 코드에서 한번 찾아보세요.). 이건 정말 심각한 메모리 낭비입니다. Tutorial 9에서 어떻게 다룰 지 배우겠습니다.
* 지금은 우리 3D 모델이 고정되어 있습니다. 모델을 수정하려면 소스 코드를 고치고 다시 어플리케이션을 컴파일한 뒤 잘 되길 바래야 합니다. Tutorial 7에서 동적인 모델을 로딩하는 방법을 배우게 됩니다.
* 실제로는 각 Vertex가 적어도 3번 적혀 있습니다.("-1.0f,-1.0f,-1.0f"을 위 코드에서 한번 찾아보세요.). 이건 정말 심각한 메모리 낭비입니다. Tutorial 9에서 어떻게 다룰 지 배우겠습니다.

이제 흰 바탕에 육면체를 그리는데 필효한 것은 다 준비 되었습니다. 쉐이더를 써보세요! 쫄지말고 한번 시도해 보세요. ^^
이제 흰 바탕에 육면체를 그리는데 필요한 것은 다 준비 되었습니다. 셰이더를 써보세요! 겁먹지 말고 한번 시도해 보세요.

# Adding colors
# 색 추가하기

A color is, conceptually, exactly the same as a position : it's just data. In OpenGL terms, they are "attributes". As a matter of fact, we already used this with glEnableVertexAttribArray() and glVertexAttribPointer(). Let's add another attribute. The code is going to be very similar.
색은 개념적으로 위치와 완전히 같은 데이터일 뿐입니다. OpenGL에서는 이들을 "Attribute"라 부릅니다. 사실 우리는 이미 glEnableVertexAttribArray()glVertexAttribPointer() 에서 그것을 사용했습니다. 코드도 아주 비슷한 형태가 될 것입니다.

First, declare your colors : one RGB triplet per vertex. Here I generated some randomly, so the result won't look that good, but you can do something better, for instance by copying the vertex's position into its own color.
가장 먼저 원하는 색상을 선언하세요. vertex 하나 당 RGB를 나타내는 세 숫자가 필요합니다. 여기에선 색을 무작위로 생성해서 보기 나쁘지만, vertex의 위치를 자신의 색상으로 설정하는 등의 다른 방법을 사용하면 더 좋게 만들 수 있습니다.

``` cpp
// One color for each vertex. They were generated randomly.
// vertex당 색상 하나 씩. 색상은 무작위로 생성되었음
static const GLfloat g_color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
Expand Down Expand Up @@ -129,7 +129,7 @@ static const GLfloat g_color_buffer_data[] = {
};
```

The buffer is created, bound and filled in the exact same way as the previous one :
이전과 완전히 같은 방식으로 버퍼가 생성되고, 연결된 뒤 채워집니다.

``` cpp
GLuint colorbuffer;
Expand All @@ -138,121 +138,121 @@ glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
```

The configuration is also identical :
설정도 동일합니다,

``` cpp
// 2nd attribute buffer : colors
// 두번째 attribute 버퍼 : 색상들
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
1, // attribute. 1인 특별한 이유는 없지만, 셰이더의 레이아웃과 같아야 합니다
3, // 크기
GL_FLOAT, // 타입
GL_FALSE, // 정규화 여부
0, // 건너뛰기(stride)
(void*)0 // 배열 버퍼 여백(offset)
);
```

Now, in the vertex shader, we have access to this additional buffer :
이제 정점(vertex) 셰이더에서 이 새로운 버퍼에 접근할 수 있습니다.

``` glsl
// Notice that the "1" here equals the "1" in glVertexAttribPointer
// 여기의 "1"이 glVertexAttribPointer의 "1"과 같습니다
layout(location = 1) in vec3 vertexColor;
```

{: .highlightglslvs }

In our case, we won't do anything fancy with it in the vertex shader. We will simply forward it to the fragment shader :
이 예제에서는 정점 셰이더로 멋진 일들은 안 할 겁니다. 바로 프래그먼트 셰이더로 전달해 주세요.

``` glsl
// Output data ; will be interpolated for each fragment.
// 출력 데이터. 각 fragment마다 보간(interpolate)될 예정입니다
out vec3 fragmentColor;

void main(){

[...]

// The color of each vertex will be interpolated
// to produce the color of each fragment
// 보간될 vertex의 색상
// 각 fragment의 색상을 만든다
fragmentColor = vertexColor;
}
```
{: .highlightglslvs }

In the fragment shader, you declare fragmentColor again :
프래그먼드 셰이더에서 fragmentColor을 다시 선언합니다.

``` glsl
// Interpolated values from the vertex shaders
// 정점 셰이더에서 가져온 보간된 값
in vec3 fragmentColor;
```
{: .highlightglslfs }

... and copy it in the final output color :
... 그리고 그 값을 최종 출력 색상으로 복사합니다.

``` glsl
// Ouput data
// 출력 데이터
out vec3 color;

void main(){
// Output color = color specified in the vertex shader,
// interpolated between all 3 surrounding vertices
// Output color = color 정점 셰이더에 명시되어 있습니다 specified in the vertex shader,
// 주변 3개의 vertex 로 보간됩니다
color = fragmentColor;
}
```
{: .highlightglslfs }

And that's what we get :
그 결과는 이렇습니다.

![]({{site.baseurl}}/assets/images/tuto-4-colored-cube/missing_z_buffer.png)


Urgh. Ugly. To understand what happens, here's what happens when you draw a "far" triangle and a "near" triangle :
못생겼죠. 무슨 일이 일어났는지 이해하기 위해, "먼"삼각형과 "가까운"삼각형을 그릴 때 어떻게 되는지 살펴봅시다.

![]({{site.baseurl}}/assets/images/tuto-4-colored-cube/FarNear.png)


Seems OK. Now draw the "far" triangle last :
지금은 괜찮아 보이죠. 이번엔 "먼"삼각형을 먼저 그립시다.

![]({{site.baseurl}}/assets/images/tuto-4-colored-cube/NearFar.png)


It overdraws the "near" one, even though it's supposed to be behind it ! This is what happens with our cube : some faces are supposed to be hidden, but since they are drawn last, they are visible. Let's call the Z-Buffer to the rescue !
"가까운"삼각형을 덮어 버립니다! 원래는 그 뒤에 있어야 하는데 말이죠. 우리의 육면체에도 같은 일이 생깁니다. 어떤 면들은 숨겨져야 하는데, 나중에 그리면 보이게 되는 거죠. Z-Buffer의 도움이 필요합니다!

*Quick Note 1* : If you don't see the problem, change your camera position to (4,3,-3)
*참고 1* : 문제가 보이지 않는다면 카메라 위치를 (4,3,-3)으로 바꿔 보세요.

*Quick Note 2* : if "color is like position, it's an attribute", why do we need to declare out vec3 fragmentColor; and in vec3 fragmentColor; for the color, and not for the position ? Because the position is actually a bit special : It's the only thing that is compulsory (or OpenGL wouldn't know where to draw the triangle !). So in the vertex shader, gl_Position is a "built-in" variable.
*참고 2* : 색상도 위치도 attribute라면, 왜 색상을 위해서만 out vec3 fragmentColor; in vec3 fragmentColor; 을 선언할까요? 사실 위치는 조금 특별하기 때문입니다. 위치는 유일하게 강제적인 attribute (이게 없으면 OpenGL은 삼각형을 어디에 그려야 할 지 모릅니다!). 따라서 gl_Position은 정점 셰이더에 "내장된"(Built-in) 변수입니다.

# The Z-Buffer
# Z-Buffer

The solution to this problem is to store the depth (i.e. "Z") component of each fragment in a buffer, and each and every time you want to write a fragment, you first check if you should (i.e the new fragment is closer than the previous one).
이 문제의 해결 방법은 각 fragment의 깊이(Z) 컴포넌트를 버퍼에 저장하고, fragment에 쓸 때마다 그 값을 (새 fragment가 이전에 그려진 것보다 가까이 있는지)확인하는 것입니다.

You can do this yourself, but it's so much simpler to just ask the hardware to do it itself :
직접 할 수도 있지만, 하드웨어에게 부탁하는 편이 훨씬 간단하죠.

``` cpp
// Enable depth test
// 깊이 검사(depth test)를 활성화
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
// 먼저 그려진 것보다 fragment가 가까이 있을 때 그린다
glDepthFunc(GL_LESS);
```

You also need to clear the depth each frame, instead of only the color :
그리고 깊이 버퍼를 매 프레임마다 비워야 합니다.

``` cpp
// Clear the screen
// 화면을 비운다
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
```

And this is enough to solve all your problems.
이렇게 문제를 모두 해결할 수 있습니다.

![]({{site.baseurl}}/assets/images/tuto-4-colored-cube/one_color_per_vertex.png)

# Exercises
# 연습

* Draw the cube AND the triangle, at different locations. You will need to generate 2 MVP matrices, to make 2 draw calls in the main loop, but only 1 shader is required.
* 육면체와 삼각형을 서로 다른 위치에 한번에 그리세요. 메인 루프 안에서 draw call 2번을 수행하기 위해 MVP 매트리스 2개가 필요하지만, 셰이더는 하나만 있으면 됩니다.


* Generate the color values yourself. Some ideas : At random, so that colors change at each run; Depending on the position of the vertex; a mix of the two; Some other creative idea :) In case you don't know C, here's the syntax :
* 색상을 직접 설정해 보세요. 예를 들어, 무작위로 실행할 때마다 바뀌게 하거나, vertex의 위치에 따라 색상이 정해지도록 해 보세요. 둘을 섞어 보기도 하고요. 다른 창의적인 아이디어도 시험해 보세요 :) C언어를 잘 모르신다면, 이 코드를 참고하세요.

``` cpp
static GLfloat g_color_buffer_data[12*3*3];
Expand All @@ -263,4 +263,4 @@ for (int v = 0; v < 12*3 ; v++){
}
```

* Once you've done that, make the colors change each frame. You'll have to call glBufferData each frame. Make sure the appropriate buffer is bound (glBindBuffer) before !
* 해 보셨다면, 매 프레임 색이 바뀌도록 만들어 보세요. 매 프레임 glBufferData를 호출해야 합니다. 알맞은 버퍼가 연결(glBindBuffer)되어 있는지 꼭 확인하세요!