- 전체
- 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
| 번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
|---|---|---|---|---|
| 11 | [jQuery] Ajax 기본 사용법 | 졸리운_곰 | 2018.08.03 | 719 |
| 10 | jQuery selector,jQuery 셀럭터, jQuery 선택자 | 졸리운_곰 | 2018.07.29 | 731 |
| 9 |
jQuery 스타일 & 속성 다루기
| 졸리운_곰 | 2018.07.29 | 790 |
| 8 | Force redraw on an element (jQuery) | 졸리운_곰 | 2018.07.28 | 638 |
| 7 | 자바스크립트에서 변수에 문자열이 있는지 체크 하는 방법 | 졸리운_곰 | 2018.06.05 | 775 |
| 6 | [jQuery] ajax 콜백함수에서 파라메터 패싱 : Pass variable to function in jquery AJAX success callback | 졸리운_곰 | 2018.06.05 | 443 |
| 5 | JQUERY – ON 을 알아보자 | 졸리운_곰 | 2018.06.04 | 450 |
| 4 | 동적으로 생성된 button의 값 가져오기! | 졸리운_곰 | 2018.06.04 | 785 |
| 3 |
jQuery 스타일 & 속성 다루기
| 졸리운_곰 | 2017.08.25 | 597 |
| 2 | remove-innerhtml-from-div 태그 안의 html코드 삭제 | 졸리운_곰 | 2017.07.08 | 633 |
| 1 | [jQuery] Ajax의 흐름과 예제 | 졸리운_곰 | 2017.01.17 | 632 |

