- Tham gia
- 21/01/2018
- Bài viết
- 728
Với snapshot 21w10a, shader giờ đây có thể insert trực tiếp vào trong resource pack mà không cần cài thêm mods nhờ OpenGL 3.1.
Hướng dẫn này mình sẽ làm custom overworld skybox với vanilla shader, còn các shader khác thì tự mò trong client jar (a.k.a /.minecraft/versions/21w10a/21w10a.jar)
I. Yêu cầu trước khi làm shader
- Snapshot 21w10a (sau này sẽ là vanilla 1.17)
- Text editor (notepad, vim, emacs, vscode, etc... Có syntax coloring thì càng tốt)
- Một chút hiểu biết về OpenGL Shading Language (Hoặc có hiểu biết về common programming language syntax, VD như C++, Java, JS)
- GPU hỗ trợ OpenGL 3.1 trở lên (Intel HD Graphics support OpenGL 4.1)
II. Hệ thống vanilla shader
Vanilla shader dựa trên OpenGL 3.1 (or OpenGL Core 3.1). Vanilla shader không tích hợp với Optifine shader nên không thể dễ dàng convert từ Optifine sang vanilla (hoặc nếu convert sẽ mất nhiều thời gian).
1. Vị trí đặt shader
Toàn bộ shader được đặt tại /assets/minecraft/shaders:
- core: Nơi đặt các shader chính. Ở đây custom skybox sẽ dùng mỗi thư mục core
- include: Giống như C++ "#include", nhưng trong shader phải dùng "#moj_import <abcxyz.glsl>"
- post: idk
- program: Nơi đặt các shader liên quan đến "Super Secret Settings" mà chỉ có thể enable ở 1.7. Hình như trong này có composition program
2. /shaders/core/*.json
File *.json được sử dụng khi uniform trong shader không được phiên bản mienkraft hỗ trợ:
- "blend": idk
- "vertex"/"fragment": Tên shader. Nếu shader là skybox.fsh thì "fragment" sẽ là "skybox"
- "attributes": Đầu vào cho shader nếu không được phiên bản mienkraft hỗ trợ
- "samplers": Texture, nhưng mà ko rõ cách load texture từ rsp
- "uniforms": Danh sách các uniform, loại uniform, array size và failback values
3. /shaders/core/*.vsh
Vertex Shader (VSH) là shader dùng cho việc position các vertex dựa trên các thuộc tính. Dùng cái này để làm lá cây rung chuyển chẳng hạn
4. /shaders/core/*.fsh
Fragment Shader (FSH) là loại shader để hiển thị màu. VD như làm rainbow block hoặc epic skybox
III. Làm custom skybox (copy and paste edition)
B1: Tạo resource pack (ofc)
B2: Tạo "position.json":
B3: Tạo "position.fsh"
B4: Thêm version và include fog.glsl:
- "#version 150": Phiên bản OpenGL mà shader này sử dụng
- "#moj_import <fog.glsl>": Include file "fog.glsl" (ở đây include từ file jar thay vì resource pack)
B5: Thêm các uniform cần thiết và fragment I/O:
- FogStart/FogEnd/FogColor: Fog thing
- ScreenSize: Kích thước màn hình game
- ProjMat: Projection matrix
- ModelViewMat: View matrix
- GameTime: Thời gian game đã chạy
B6: Thêm hàm 3d perlin noise (copy tại https://github.com/BrianSharpe/Wombat/blob/master/SimplexPerlin3D.glsl)
B7: Thêm hàm castSky:
- "vec3 v" là tham số của hàm castSky. Tham số này là hướng của player view ray lên skybox
- Hàm này phải trả về giá trị "vec3", là giá trị màu RGB dựa trên hướng của player view ray
Ở đây mình dùng hàm perlin noise ở trên để tạo ra clouds:
B8: Thêm hàm main:
- Phần thứ nhất là để lấy relative position. Thông thường, gl_FragCoord trả về giá trị dựa trên vị trí pixel trên màn hình. Ở đây convert thành vector 2d với mỗi giá trị X và Y đi từ -1 đến 1
- Phần thứ hai là tính toán vị trí để cast ray lên skybox
- Phần thứ ba là phần check ray. Nếu ray hướng xuống thì trả về giá trị default. Nếu bỏ phần này sẽ thấy clouds ở dưới void
- Phần thứ tư trả về giá trị sau khi cast lên skybox
B9: enjoy
bonus: lên shadertoy xong tìm cái j ngon thì implement vào, vd như www.shadertoy.com
Hướng dẫn này mình sẽ làm custom overworld skybox với vanilla shader, còn các shader khác thì tự mò trong client jar (a.k.a /.minecraft/versions/21w10a/21w10a.jar)
I. Yêu cầu trước khi làm shader
- Snapshot 21w10a (sau này sẽ là vanilla 1.17)
- Text editor (notepad, vim, emacs, vscode, etc... Có syntax coloring thì càng tốt)
- Một chút hiểu biết về OpenGL Shading Language (Hoặc có hiểu biết về common programming language syntax, VD như C++, Java, JS)
- GPU hỗ trợ OpenGL 3.1 trở lên (Intel HD Graphics support OpenGL 4.1)
II. Hệ thống vanilla shader
Vanilla shader dựa trên OpenGL 3.1 (or OpenGL Core 3.1). Vanilla shader không tích hợp với Optifine shader nên không thể dễ dàng convert từ Optifine sang vanilla (hoặc nếu convert sẽ mất nhiều thời gian).
1. Vị trí đặt shader
Toàn bộ shader được đặt tại /assets/minecraft/shaders:
- core: Nơi đặt các shader chính. Ở đây custom skybox sẽ dùng mỗi thư mục core
- include: Giống như C++ "#include", nhưng trong shader phải dùng "#moj_import <abcxyz.glsl>"
- post: idk
- program: Nơi đặt các shader liên quan đến "Super Secret Settings" mà chỉ có thể enable ở 1.7. Hình như trong này có composition program
2. /shaders/core/*.json
File *.json được sử dụng khi uniform trong shader không được phiên bản mienkraft hỗ trợ:
- "blend": idk
- "vertex"/"fragment": Tên shader. Nếu shader là skybox.fsh thì "fragment" sẽ là "skybox"
- "attributes": Đầu vào cho shader nếu không được phiên bản mienkraft hỗ trợ
- "samplers": Texture, nhưng mà ko rõ cách load texture từ rsp
- "uniforms": Danh sách các uniform, loại uniform, array size và failback values
3. /shaders/core/*.vsh
Vertex Shader (VSH) là shader dùng cho việc position các vertex dựa trên các thuộc tính. Dùng cái này để làm lá cây rung chuyển chẳng hạn
4. /shaders/core/*.fsh
Fragment Shader (FSH) là loại shader để hiển thị màu. VD như làm rainbow block hoặc epic skybox
III. Làm custom skybox (copy and paste edition)
B1: Tạo resource pack (ofc)
B2: Tạo "position.json":
JSON:
{
"blend": {
"func": "add",
"srcrgb": "srcalpha",
"dstrgb": "1-srcalpha"
},
"vertex": "position",
"fragment": "position",
"attributes": [
],
"samplers": [
],
"uniforms": [
{ "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] },
{ "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] },
{ "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] },
{ "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] },
{ "name": "ScreenSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] },
{ "name": "GameTime", "type": "float", "count": 1, "values": [ 0.0 ] },
{ "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }
]
}
B3: Tạo "position.fsh"
B4: Thêm version và include fog.glsl:
Mã:
#version 150
#moj_import <fog.glsl>
- "#moj_import <fog.glsl>": Include file "fog.glsl" (ở đây include từ file jar thay vì resource pack)
B5: Thêm các uniform cần thiết và fragment I/O:
Mã:
uniform vec4 ColorModulator;
uniform float FogStart;
uniform float FogEnd;
uniform vec4 FogColor;
uniform vec2 ScreenSize;
uniform mat4 ProjMat;
uniform mat4 ModelViewMat;
uniform float GameTime;
in float vertexDistance;
out vec4 fragColor;
- ScreenSize: Kích thước màn hình game
- ProjMat: Projection matrix
- ModelViewMat: View matrix
- GameTime: Thời gian game đã chạy
B6: Thêm hàm 3d perlin noise (copy tại https://github.com/BrianSharpe/Wombat/blob/master/SimplexPerlin3D.glsl)
B7: Thêm hàm castSky:
Mã:
vec3 castSky(vec3 v) {
// code here
}
- Hàm này phải trả về giá trị "vec3", là giá trị màu RGB dựa trên hướng của player view ray
Ở đây mình dùng hàm perlin noise ở trên để tạo ra clouds:
Mã:
float time = GameTime * 10.0;
v.x += time;
float sky1 = snoise(v * 2.0) * 0.25;
float sky2 = max(snoise(v * 10.0) * 0.15, -0.1);
float sky3 = max(snoise(v * 50.0) * 0.03, -0.5);
vec3 sky = vec3(max(sky1 + sky2 + sky3, 0.0));
return sky;
B8: Thêm hàm main:
Mã:
void main() {
vec2 pos = gl_FragCoord.xy / ScreenSize;
pos -= vec2(0.5, 0.5);
pos *= 2;
vec4 cast_pos = vec4(pos, 1.0, 1.0);
cast_pos = normalize(inverse(ProjMat) * cast_pos);
vec3 v = normalize(cast_pos.xyz * mat3(ModelViewMat));
if (v.y < 0) {
fragColor = linear_fog(ColorModulator, vertexDistance, FogStart, FogEnd, FogColor);
return;
}
vec4 color = linear_fog(ColorModulator, vertexDistance, FogStart, FogEnd, FogColor);
color += vec4(castSky(v), 1.0) * 12.0 / vertexDistance;
fragColor = color;
}
- Phần thứ hai là tính toán vị trí để cast ray lên skybox
- Phần thứ ba là phần check ray. Nếu ray hướng xuống thì trả về giá trị default. Nếu bỏ phần này sẽ thấy clouds ở dưới void
- Phần thứ tư trả về giá trị sau khi cast lên skybox
B9: enjoy
bonus: lên shadertoy xong tìm cái j ngon thì implement vào, vd như www.shadertoy.com
