固体几何缓冲
几何分类
在 OptiFine 中,整个场景被拆分到了将近 20 个几何缓冲,要为它们逐一编写处理程序会在今后的修改带来很多不必要的麻烦。
大多数几何的处理方法应该是相似的,因此我们可以将它们分门别类,然后为每一类几何缓冲编写一个统一的程序。在之前,我们浅用了 #include
命令进行函数包含。这里我们将更进一步,使其包含整个着色器程序:
#ifdef VERTEX_STAGE
[... 顶点着色器程序 ...]
#endif
#ifdef FRAGMENT_STAGE
[... 片段着色器程序 ...]
#endif
将其放入一个新的文件夹 shaders\programs\
,这里的内容都是直接使用的着色器程序。最后在各几何缓冲的顶点和片段阶段调用对应的内容:
#version 330 core
#define GBUFFER_SHADER
#define VERTEX_STAGE
#include "/programs/<程序>"
有一些内容大致相同,但是存在细微差异的着色器程序,我们可以使用 #ifdef
进行判定。
在上一章中,我们已经处理完成了地形(terrain
),在几何缓冲中基本上就只有它会绘制环境光遮蔽,因此我们可以将其设置为单独的一类。为了便于今后的维护,即使只有一个几何缓冲使用的着色器我们也将会把主要的程序代码存入 programs\
下,对于 terrain
来说,我们直接使用同名文件 gbuffers_terrain.glsl
即可。
在本章中,我们的其他几何缓冲程序都将以 terrain
程序为蓝本编写。如果你忘记了我们之前的着色器,或者没有完成上一章提取原版光照强度的习题(不做作业可不行哦),这里有一份参考蓝本:
#include "/libs/Uniforms.glsl"
#ifdef VERTEX_STAGE
#include "/libs/Attributes.glsl"
out VS_OUT {
vec4 color;
vec2 uv;
vec3 normal;
vec2 vanillaLightStrength;
} vs_out;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(vaPosition + chunkOffset, 1.0);
vs_out.color = vaColor;
vs_out.normal = normalMatrix * vaNormal;
vs_out.uv = vec2(textureMatrix * vec4(vaUV0, vec2(1.0)));
vs_out.vanillaLightStrength = vec2(vaUV2 / 16) / textureSize(lightmap, 0);
}
#endif
#ifdef FRAGMENT_STAGE
in VS_OUT {
vec4 color;
vec2 uv;
vec3 normal;
vec2 vanillaLightStrength;
} fs_in;
/* DRAWBUFFERS:012 */
layout(location = 0) out vec4 fragColor;
layout(location = 1) out vec3 normals;
layout(location = 2) out vec2 light;
void main() {
fragColor = texture(gtexture, fs_in.uv) * fs_in.color;
if(fragColor.a <= alphaTestRef) discard;
fragColor.a = fs_in.color.a;
normals = fs_in.normal *.5+.5;
light = fs_in.vanillaLightStrength;
}
#endif
混合
由于几何缓冲程序向缓冲区输出内容之后不会翻转缓冲区,OptiFine 中的一些几何缓冲默认启用了混合 (Blending)。GL 可以通过混合方程 (Blend Equation)让一些内容在输出时与缓冲区上已有内容进行色彩混合。
其中
表示混合结果;
表示源(从程序输出)颜色;
表示源因子,决定源颜色的乘数;
表示目标(缓冲区中)颜色;
表示目标因子,决定目标颜色的乘数。
例如,当我们将 设置为源的 Alpha 通道 ,然后将 设置为 ,则最终的颜色为
即将源颜色根据其不透明度与缓冲区的颜色进行混合,效果与 mix(SRC_COLOR, DST_COLOR, SRC_ALPHA)
相同。
此外,OptiFine 允许我们单独对 Alpha 通道设置混合方式:
设置混合
我们可以在 shaders.properties
中使用 blend.<程序>
按
的顺序设置混合因子 ,如:
blend.gbuffers_terrain = <off|src dst srcA dstA>
每个因子可以使用下列参数:
参数 | 值 | 备注 |
---|
off
| 禁用混合 | 只需设置一个因子 |
ZERO
|
| |
ONE
|
| |
SRC_COLOR
|
| 各通道独立相乘 |
ONE_MINUS_SRC_COLOR
|
| 各通道独立相乘 |
DST_COLOR
|
| 各通道独立相乘 |
ONE_MINUS_DST_COLOR
|
| 各通道独立相乘 |
SRC_ALPHA
|
| |
ONE_MINUS_SRC_ALPHA
|
| |
DST_ALPHA
|
| |
ONE_MINUS_DST_ALPHA
|
| |
SRC_ALPHA_SATURATE
|
| |
也可以逐个缓冲区设置混合模式,如:
blend.gbuffers_entities.colortex0 = <off|src dst srcA dstA>
09 四月 2025