- 전체
- HTML
- Web Design (웹디자인)
- XE 응용 개발
- wordpress plugin dev
- Javascript & JavaScript Application
- MEAN Stack : full stack javascript
- angular js & ionic framework
- bootstrap
- WebGL, Three.js and Babylon.js
- restful api design
- mobile web
- node.js 응용
- Cloud Service 응용
- 웹 어셈블리 개발 [WASM, WebAssembly]
- 마이크로서비스, MSA (microservice architecture)
- WebGL / WebGPU
- next.js 개발
- micro frontend (마이크로프론트앤드)
- 전자상거래/쇼핑몰
- 서버 클라우드 (aws, azure, google)
WebGL, Three.js and Babylon.js Custom shaders with Three.JS: Uniforms, textures and lighting
2017.08.10 21:34
Custom shaders with Three.JS: Uniforms, textures and lighting
If you’re familiar to WebGL and GLSL programming and have started using three.js, you’ll eventually run into a situation where you want to code your own shader, but at the same time use the resources that this library provides you with. In this post, I’ll show you how to setup a custom shader with a three.js geometry, pass it your own uniforms, bind a texture to a particular uniform and receive all lights that you’ve added to the scene.
Source code for demo
The source code below has been tested with three.js r84 and can be visualized here.
|
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
|
And this is the source for the render.js file:
|
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
|
There’s nothing special about the init() function: It sets up the webgl renderer, creates the scene, the camera and a point light and adds an object to the scene. The function getPlaneGeometry() just instantiates a THREE.PlaneGeometry, which contains vertices, normals, and texture coordinates. The anonymous function on line 61 will create our mesh object. In three.js, a mesh is a “renderable” type formed by combining a geometry (from which three.js will create a vertex buffer object) and a material (which is basically a shader with metadata, such as uniforms). Here, we create a ShaderMaterial, which allows us to specify our custom vertex and fragment shaders. The “uniforms” parameter takes an object with the format:
|
1 2 3 4 |
|
For a guide on accepted formats, consult here. In this example, I created a float uniform named lightIntensity and a texture sampler uniform named, well, textureSampler.
Finally, on function animate I update the color uniform to a simple sinusoidal function. Three.js will automatically send the current value of each uniform to the GPU every time you call render.
Vertex shader and implicit attributes and uniforms
If you paid close attention to the vertex shader code, you’ve probably noticed that the declaration for the “position” attribute seems to be missing. The same also applies to the projectionMatrix and modelViewMatrix. In fact, three.js modifies the vertex shader given to it by appending the declaration of several attributes and uniforms. To understand the fields that are automatically created by three.js, refer to the WebGLProgram documentation.
Texture Sampler Uniform
In three.js, texture sampler uniforms have a type "t" and must be assigned to THREE.Texture objects. If your texture is an image, there’s a helper function that simplifies this task:
|
1 2 3 |
|
After I’ve chosen the texture image (remember to use an image whose dimensions are powers of two), our shader material is initialized in the matvariable.
Here I’ve loaded the image file and created a THREE.Texture object. I also set the magnification filter to nearest (I want my texture to be pixelated as I scale it up). More information on the filter constants used by three.js can be found on the texture constants documentation. You can also see the fields for the THREE.Texture object here.
Another important property introduced is the transparent flag, since my texture has some regions with alpha=0. By setting the transparent flag to true, three.js will automatically call gl.enable(GL_BLEND) when this object is about to be drawn. It also defers the rendering of transparent objects to after opaque objects are drawn. Also, three.js draws these objects ordered from the farthest to the closest ones.
Now that we’ve seen how to create a shader material, let’s take a look at the shader code itself.
Dealing with lights
In order to deal with light objects in your shader, you have to manually setup the required uniforms both on the material object and in your shader code.
Setting up the material
The first thing you have to do is to enable the lights flag in the material object by setting this field to true.
You also have to include the required light objects in the uniform list of your material object. Since three.js already has a public field with all light uniforms (and there’s a lot of them) in THREE.UniformsLib['lights'], you can merge them to your uniform object with the function THREE.UniformUtils.merge:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Create some lights
In order to test our demo, we create a point light right in front of our object. This must be done before the character creation, making sure that THREE.UniformsLib['lights'] contain the required light objects.
|
1 2 3 4 |
|
Setting up the shader
In our demo, three.js is automatically sending all your lights to our light uniforms. Since we are using a point light, we’ll need to create the following uniform:
|
1 2 3 4 5 6 7 8 9 10 11 |
|
Notice that the PointLight structure is in (a partial) format expected by three.js to provide the data relative to Point Lights to the shader program. In the UniformsLib documentation you can see a list of all such uniforms provided by the THREE.UniformsLib. You can also see their shader implementation here. Notice that the constant NUM_POINT_LIGHTS is automatically created by three.js, so no need to worry about it.
And that’s it! This is how the final character looks like:
Adding lights at any moment (aka adding lights at runtime)
So you want to add a light after your shader programs were compiled and are running (for instance, you may have a candle being lit in the middle of the gameplay). Two steps are required. First, add the light to the scene, as explained previously. Then, for each material (make sure you have access to them), set its needsUpdate flag to true. That should get your shader recompiled to take into account the new number of lights.
|
1 2 3 4 |
|
If you have access to your character (and any objects that contain a material), you can access its material in the “material” field:
|
1 |
|
Notice that you will have to do that to all materials in your scene (or at least those you think that will be affected). Also, you only have to perform shader recompilation if the number of similar lights is changed, since you would be changing the NUM_*_LIGHTS constant. Keep in mind that, if you add a point light and remove a spotlight, you will still need to update your material, as both the number of spotlights and point lights have changed.
Final thoughts
This is a pretty basic example that shows how to setup a custom shader with textures and three.js lights. Although the final effect could have been easily achieved without touching any shader, I hope this will prove useful to someone willing to write a shader that’s not available in the standard three.js material list.
Considering the fact that most cool effects are achievable by multipass rendering, I’ll eventually extend this post in the future to cover that subject as well.
[출처] https://csantosbh.wordpress.com/2014/01/09/custom-shaders-with-three-js-uniforms-textures-and-lighting/
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
댓글 0
| 번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
|---|---|---|---|---|
| 8 | 제로보드 XE의 최근 게시글 5개를 DB에서 직접 조회 | 졸리운_곰 | 2020.08.04 | 456 |
| 7 | python 으로 XE mysql 쿼리로 자동 게시물 등록하기 | 졸리운_곰 | 2020.03.03 | 448 |
| 6 | [WP]외부 게시판을 IFRAME으로 넣기 | 졸리운_곰 | 2019.01.30 | 533 |
| 5 | XE(제로보드) 게시판 내 스크립트 사용하기 | 가을의곰 | 2017.06.18 | 734 |
| 4 | XE 새 템플릿 문법으로 원하는 위치(head, body)에 JS 선언하기. | 가을의곰 | 2017.06.18 | 308 |
| 3 | 예제를 통해 쉽게 읽어보는 XE모듈개발 시작하기 | 졸리운_곰 | 2016.05.10 | 585 |
| 2 | [시니시즘] 비회원에게 파일 다운로드 권한이 없다고 뜰 때 | 졸리운_곰 | 2016.04.14 | 766 |
| 1 | XE 템플릿 구문 | 졸리운_곰 | 2015.05.12 | 1135 |

