我在mcforum上逛的时候看见了一个貌似不错的教程 感到有趣 于是决定尽我所能翻译它 如有任何错误请指出 谢谢
希望不会已经有人翻译过了
有glsl问题不要问我
这只是一个基础教程 会光影的大神请绕路
原文minecraftforum.net/forums/resource-pack-discussion/1255965
@tsd1 @719220502 @⊙v⊙ @乙烯_中国 @719823597 @pacerrecap @pca006132
章节
- 着色器导论
- 计算机如何理解颜色
- 向量
- glsl数据类型和声明变量
- glsl格式
- 函数
- 例子
- minecraft着色器文件系统
第一节 着色器导论
在你开始前,你需要对着色器有个概念。着色器是一段在显示器显示前修改3d的对象的代码。着色器有两种,分别是顶点着色器和片元着色器。顶点着色器修改3d对象的几何尺寸,而片元着色器修改画到屏幕的像素。在原版minecraft中,着色器访问不了3d尺寸,所以你完全不用理会顶点着色器。
这是一个最简单的片元着色器:
- uniform sampler2D DiffuseSampler;
- varying vec2 texCoord;
- void main() {
- gl_FragColor = texture2D(DiffuseSampler, texCoord);
- }
- uniform sampler2D DiffuseSampler;
- varying vec2 texCoord;
"gl_FragColor"是着色器的输出。它的值就是将要显示的颜色。
第二节 计算机如何理解颜色
现在,为了让你知道如何编辑颜色,你需要懂得计算机是如何理解颜色的。
每个屏幕上的像素由三色光组成。分别是红光、绿光和蓝光。
在着色器里,1代表完全点亮,0表示完全熄灭,0.5表示半亮半灭。
三个颜色总是按照红绿蓝的顺序排列的。(这就是RGB这个词的来源)
(1,1,1) 代表白色
(0,0,0) 代表黑色
(1,0,0) 代表红色
(0,1,0) 代表绿色
(0,0.5,0) 代表深绿色
在你继续前请确保你熟练掌握RGB。
第三节 向量
向量是一组数,glsl中的颜色是用向量表示的。对向量做乘法就是把他的各个分量分别乘起来。
例如:
(1,2,3) x (1,2,3) = (1,4,9)
你也可以用一个数来乘向量。这就是用向量的各个分量分别乘以这个数。
(1,2,3) x 4 = (4,8,12)
第四节 glsl数据类型和声明变量
glsl有许多数据类型,包括向量。
向量可以是各种不同的大小,这是创建他们的方法:
vec2(1.0,1.0)
vec3(1.0,1.0,1.0)
vec4(1.0,1.0,1.0,1.0)
通常使用vec4来表示颜色
每个分量都在0和1之间
这些数依次代表红绿蓝和透明度。
透明度是颜色透明的程度。若他是0,颜色是不可见的。若他是0.5,他是半透明的。等等。
注意:永远要在你用的所有的数后面加上小数位。glsl对待整数和浮点数是不一样的。把它们混在一起会引起BUG。
这是你在glsl中声明一个变量的方法(如果你不知道啥是变量,Google它)。
- [type] [name] = [value];
你可以用的type包括向量:"vec2","vec3","vec4"
还有数:"float","int" (除非你知道你在干什么,不要用int)
例如:
- vec4 myColor = vec4(1.0,1.0,1.0,1.0);
- float myNumber = 3.0;
注意:每个操作后面都要有一个分号:";"
第五节 glsl格式
让我们回到我们最初的例子
- uniform sampler2D DiffuseSampler;
- varying vec2 texCoord;
- void main() {
- gl_FragColor = texture2D(DiffuseSampler, texCoord);
- }
我们将像素点的颜色存储到变量中。
- uniform sampler2D DiffuseSampler;
- varying vec2 texCoord;
- void main() {
- vec4 color = texture2D(DiffuseSampler, texCoord);
- gl_FragColor = color;
- }
glsl拥有这些运算
加: +
减: -
乘: *
除: /
我们用*将这颜色乘以一个系数
- uniform sampler2D DiffuseSampler;
- varying vec2 texCoord;
- void main() {
- vec4 color = texture2D(DiffuseSampler, texCoord);
- gl_FragColor = color*1.5;
- }
如果我们只想将图中红色分量放大呢?
- uniform sampler2D DiffuseSampler;
- varying vec2 texCoord;
- void main() {
- vec4 color = texture2D(DiffuseSampler, texCoord);
- gl_FragColor = color*vec4(1.5,1.0,1.0,1.0);
- }
你可以像这样获得 color 的各个分量
color.r
color.g
color.b
color.a
下面是你在黑白着色器中使用它的方法:
- uniform sampler2D DiffuseSampler;
- varying vec2 texCoord;
- void main() {
- vec4 color = texture2D(DiffuseSampler, texCoord);
- vec4 average = (color.r+color.g+color.b)/3.0;
- gl_FragColor = vec4(average,average,average,1.0);
- }
译注 原文如此 中间的vec4 average那里似乎是float average
(notice how you can use parentheses)
你也可使用xyzw获得向量的分量
如果一个向量代表坐标 你就可以这样获得x坐标
vector.x;
你也可以用这个输出多个量 比如说 这个着色器对换红色和蓝色通道
- uniform sampler2D DiffuseSampler;
- varying vec2 texCoord;
- void main() {
- vec4 color = texture2D(DiffuseSampler, texCoord);
- gl_FragColor = color.bgra;
- }
glsl也可以使用条件语句
- if(color<3){
- }else{
- }
还有循环 (大括号中所有语句会执行5次)
- float i;
- for (i = 0; i < 5.0; i++){
- }
第六节 函数
你能够让一些代码重复使用(通常称为函数或子程序)
- vec4 brighten( vec4 input )
- {
- vec4 output = input*1.5;
- return output;
- }
接下来 你就可以任意使用它了 像这样
- vec4 newColor = brighten(color);
这里有一些有用的程序
- vec4 RGBtoHSL( vec4 col )
- {
- float red = col.r;
- float green = col.g;
- float blue = col.b;
- float minc = min(min( col.r, col.g),col.B) ;
- float maxc = max(max( col.r, col.g),col.B);
- float delta = maxc - minc;
- float lum = (minc + maxc) * 0.5;
- float sat = 0.0;
- float hue = 0.0;
- if (lum > 0.0 &amp;&amp; lum < 1.0) {
- float mul = (lum < 0.5) ? (lum) : (1.0-lum);
- sat = delta / (mul * 2.0);
- }
- vec3 masks = vec3(
- (maxc == red &amp;&amp; maxc != green) ? 1.0 : 0.0,
- (maxc == green &amp;&amp; maxc != blue) ? 1.0 : 0.0,
- (maxc == blue &amp;&amp; maxc != red) ? 1.0 : 0.0
- );
- vec3 adds = vec3(
- ((green - blue ) / delta),
- 2.0 + ((blue - red ) / delta),
- 4.0 + ((red - green) / delta)
- );
- float deltaGtz = (delta > 0.0) ? 1.0 : 0.0;
- hue += dot( adds, masks );
- hue *= deltaGtz;
- hue /= 6.0;
- if (hue < 0.0)
- hue += 1.0;
- return vec4( hue, sat, lum, col.a );
- }
- vec4 HSLtoRGB( vec4 col )
- {
- const float onethird = 1.0 / 3.0;
- const float twothird = 2.0 / 3.0;
- const float rcpsixth = 6.0;
- float hue = col.x;
- float sat = col.y;
- float lum = col.z;
- vec3 xt = vec3(
- rcpsixth * (hue - twothird),
- 0.0,
- rcpsixth * (1.0 - hue)
- );
- if (hue < twothird) {
- xt.r = 0.0;
- xt.g = rcpsixth * (twothird - hue);
- xt.b = rcpsixth * (hue - onethird);
- }
- if (hue < onethird) {
- xt.r = rcpsixth * (onethird - hue);
- xt.g = rcpsixth * hue;
- xt.b = 0.0;
- }
- xt = min( xt, 1.0 );
- float sat2 = 2.0 * sat;
- float satinv = 1.0 - sat;
- float luminv = 1.0 - lum;
- float lum2m1 = (2.0 * lum) - 1.0;
- vec3 ct = (sat2 * xt) + satinv;
- vec3 rgb;
- if (lum >= 0.5)
- rgb = (luminv * ct) + lum2m1;
- else rgb = lum * ct;
- return vec4( rgb, col.a );
- }
第七节 例子
一个简单的爆炸着色器
- uniform sampler2D DiffuseSampler;
- varying vec2 texCoord;
- //width of steps (higher numbers make quality worse)
- const float blurWidth=0.001;
- //number of steps (higher numbers cause more lag)
- const float blurSteps=8.0;
- //bloom brightness
- const float amount=1.0;
- void main() {
- vec4 color=texture2D(DiffuseSampler, texCoord);
- float brightness=(color.r+color.g+color.b)/3.0;
- vec4 sum = vec4(0);
- float j;
- float i;
- const float foo = 10.0/( ((blurSteps*2.0)+1.0)*((blurSteps*2.0)+1.0) );
- for( i= -blurSteps ;i < blurSteps; i++){
- for (j = -blurSteps; j < blurSteps; j++){
- sum += texture2D(DiffuseSampler, texCoord + vec2(j, i)*blurWidth);
- }
- }
- sum*=foo;
- vec4 modifier = sum*sum*(0.015-(brightness*0.01));
- vec4 outputColor = modifier*amount + color;
- gl_FragColor = outputColor;
- }
原版着色器可以放在资源包里
这里有一个你能够魔改的范例着色器材质
http://pack.maloweb.com/willpackshaders.zip
未完待续。。。