Translation Three.js is a great open source WebGL library. WebGL allows JavaScript to operate the GPU and achieve true 3D on the browser side. However, this technology is still in the development stage, and the information is extremely scarce. Enthusiasts basically have to learn through the Demo source code and the source code of Three.js itself.
0. Introduction I have already given an article "Start Using Three.js" before. If you haven't read it yet, you may want to. The basis of this article is based on that tutorial.
I would like to discuss shaders. Native WebGL was great until Three.js saved you a lot of trouble. Sometimes, you may want to achieve some specific effects, or want to delve a little deeper into what is displayed on your screen, then shaders will definitely enter your field of vision. If you're like me, you also want to implement something more interesting than the basics in the last tutorial. In this tutorial, I will explain the basics of Three.js, which actually do a lot of boring work for us.
Before I start, I would also like to say that this tutorial will spend quite a bit of time explaining the shader code. There will be a tutorial later that will go a little further on the basis of the shader code and use the shader to do something. . This is because shaders are not easy to understand at first glance and require some explanation.
1. Two shaders WebGL does not have a fixed rendering pipeline, and you cannot directly use a black box shader (Translator's Note: Graphics cards in the last century basically only support Fixed rendering pipeline); WebGL provides a programmable pipeline, which is more powerful but also harder to understand and use. Long story short, a programmable rendering pipeline means that the programmer is responsible for getting the vertices and drawing them to the screen. Shaders are part of the rendering pipeline. There are two types of shaders:
1. Vertex shader
2. Fragment shader
What you should know is that both of these shaders run entirely on the graphics card On the GPU, we offload the data that needs to be processed from the CPU and load it on the GPU, which reduces the burden on the CPU. Modern GPUs have greatly optimized the types of operations that shaders need to call, and it is worth doing so.
2. Vertex shader Primitive shapes, such as a sphere, are made up of vertices, right? The vertex shader is passed one of these vertices in turn and processes it. How to handle each vertex is freely customizable, but one thing the vertex shader must do is to assign a value to a variable named gl_Position, which is a 4-dimensional array that represents the final position of the vertex on the screen. This in itself is an interesting process, because we are actually talking about how to convert a three-dimensional coordinate (a vertex with x, y, z values) into, or project to a two-dimensional screen. Thankfully, we can access gl_Position so easily if we use a tool like Three.js.
3. Fragment shader Now that we have a three-dimensional object containing vertices, we need to project the object onto a two-dimensional screen, but where does the color go? What about textures and lighting? This is what the fragment shader handles.
Similar to the vertex shader, the fragment shader has a task that must be completed: setting or eliminating the variable gl_FragColor, another four-dimensional floating point variable, which is the final color of the fragment point. What is a piece? Imagine a triangle with three vertices. Fragments are all points inside the triangle calculated from these three vertices. Therefore, fragment values are interpolated from vertex values. If the color of one vertex is red and the color of the adjacent vertex is blue, then we can observe the color gradient from near the red vertex, from red to purple, and finally to blue near the blue vertex.
4. Shader variables When it comes to shader variables, there are three types: Uniforma, Attributes and Varyings. When I first heard these three words, I was confused because they didn't match anything I had used before. But now, you can understand them like this:
1. Uniforms variables can be passed into either the vertex shader or the fragment shader. They contain variables that remain unchanged throughout the rendering process, such as, The position of a point light source.
2.Attributes variables correspond to each vertex, they can only be passed into the vertex shader, for example, each vertex has a color. The relationship between Attributes variables and vertices is one-to-one correspondence.
3.Varyings variables are variables defined in the vertex shader and prepared to be passed to the fragment shader. To ensure this, we need to ensure that the variables are typed and named exactly the same in both shaders. A classic application is the normal vector, because normals are needed when calculating lighting.
In the next tutorial, I will use these three variables, and you will also learn how these three variables are actually used.
Now, we've talked about the vertex shader, the fragment shader, and the three shader variables. It's time to look at the simplest shader we can create.
5. Hello World(번역자 Tucao: 프랑스어 자랑 좀 그만해주세요) 여기 가장 간단한 버텍스 셰이더가 있습니다:
/**
* 각 정점 좌표에 모델 뷰 행렬을 곱한 후 투영 행렬을 곱합니다
* 2D 화면의 좌표를 구합니다
*/
void main() {
gl_Position =projectionMatrix *
modelViewMatrix *
vec4(position,1.0);
}
간단한 프래그먼트 셰이더:
/**
* 모든 픽셀 색상을 분홍색으로 설정
*/
void main() {
gl_FragColor = vec4(1.0, / / R
0.0, // G
1.0, // B
1.0) // A
}
그게 다입니다. 지금 바로 실행해보면 화면에 "매트" 핑크색 모양이 나타나는 것을 볼 수 있습니다. 별로 복잡하지 않죠?
버텍스 셰이더에서는 Three.js를 통해 일부 유니폼 변수를 전달합니다. 두 개의 4×4 행렬 균일 변수가 있습니다: 모델뷰 행렬과 투영 행렬. 이 두 행렬이 어떻게 작동하는지에 대해 많이 알 필요는 없습니다. 간단히 말해서, 이 두 행렬은 3차원 점 좌표가 2차원 화면의 좌표에 투영되는 방식을 설명합니다.
사실 이 두 개의 짧은 단편만 다루었습니다. Three.js는 이를 셰이더 코드 앞에 추가하므로 걱정할 필요가 없습니다. 솔직히 말해서 Three.js는 조명 데이터, 노드 색상, 노드 법선 벡터 등과 같은 많은 항목을 코드 앞에 추가하기도 합니다. Three.js가 없었다면 이러한 개체를 직접 만들고 설정해야 했습니다.
6. 셰이더 소재 사용
/**
* JQuery
*를 사용하여 DOM에서 셰이더 코드 텍스트를 추출할 수 있다고 가정합니다
*/
var vShader = $('vertexshader')
var fShader = $('fragmentsshader')
varshaderMaterial =
new THREE.ShaderMaterial ({
vertexShader: vShader.text(),
fragmentShader: fShader.text()
})
여기에서 Three.js가 컴파일되고 셰이더를 실행하고 생성한 재질에 연결하면 재질이 생성한 메시에 연결됩니다. 실제보다 더 쉬워지는 것은 아닙니다. 그럴 수도 있지만 우리는 브라우저 3D 프로그래밍에 대해 생각하고 있으며 이 주제에는 어느 정도 복잡성이 있을 것이라고 예상해야 한다고 생각합니다.
셰이더 재질과 같은 두 가지 다른 속성인 유니폼과 속성을 추가할 수도 있습니다. 벡터, 정수 또는 부동 소수점일 수 있지만 이전에 말했듯이 유니폼 변수는 모든 지점에서 일정하게 유지되므로 단일 값일 가능성이 더 높지만 속성 변수는 정점별로 있으므로 배열이어야 합니다. 메쉬에서 속성 변수와 정점은 일대일 대응을 가져야 합니다.
7. 요약 사실 이번 튜토리얼은 여기까지입니다. 사실 많은 이야기를 했지만 여러 면에서 훑어볼 뿐입니다. 다음 튜토리얼에서는 조명 효과를 시뮬레이션하기 위해 일부 속성 변수와 유니폼 변수를 전달하는 복잡한 셰이더를 제공할 것입니다.
이 튜토리얼의
소스 코드를 패키징했습니다. 다운로드하여 참조할 수 있습니다.