В настоящее время я пытаюсь реализовать Ambient Occlusion в простом Voxel Renderer, каждый блок визуализируется (если не виден) с 24 вершинами и 12 треугольниками, так что никаких зацеплений нет.
Я следовал этот учебник о том, как может работать окружающая окклюзия для миров, похожих на майнкрафт, но он не объяснил, как на самом деле реализовать это в шейдерах / графическом программировании, так что то, что я сделал до сих пор, это только мои необразованные лучшие догадки.
Основная идея c заключается в том, чтобы каждая вершина генерировала значение из окружающих блоков о том, насколько «темной» должна быть окружающая окклюзия. , (Не берите в голову мои ценности, являющиеся полностью неправильными в настоящее время). Это от 0 (без окружения) до 3 (полностью окруженная вершина). Картинка в уроке, который я связал, помогает объяснить это.
Итак, я попробовал это, но, похоже, не затемняет область вокруг вершины, но вместо этого весь треугольник, вершина находится в ... Как я могу заставить это не делать этого? Я абсолютный новичок в шейдерах и графическом программировании, поэтому любая помощь приветствуется: D
Вот мой вершинный шейдер, входные данные
- позиция вершины
- нормаль вершины
- tex_coord в текстурном атласе
- tile_uv: позиция в блоке (0 или 1 для левого / правого нижнего / верхнего угла)
- значение ambient_occlusion
#version 450
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 tex_coord;
layout(location = 3) in vec2 tile_uv;
layout(location = 4) in uint ambient_occlusion;
layout(location = 0) out vec3 v_position;
layout(location = 1) out vec3 v_normal;
layout(location = 2) out vec2 v_tex_coord;
layout(location = 3) out vec2 v_tile_uv;
layout(location = 4) out uint v_ambient_occlusion;
layout(set = 0, binding = 0) uniform Data {
mat4 world;
mat4 view;
mat4 proj;
vec2 tile_size;
} uniforms;
void main() {
mat4 worldview = uniforms.view * uniforms.world;
v_normal = mat3(transpose(inverse(uniforms.world))) * normal;
v_tex_coord = tex_coord;
v_tile_uv = tile_uv;
v_position = vec3(uniforms.world * vec4(position, 1.0));
v_ambient_occlusion = ambient_occlusion;
gl_Position = uniforms.proj * worldview * vec4(position.x, position.y, position.z, 1.0);
}
А вот мой фрагментный шейдер:
#version 450
layout(location = 0) in vec3 v_position;
layout(location = 1) in vec3 v_normal;
layout(location = 2) in vec2 v_tex_coord;
layout(location = 3) in vec2 v_tile_uv;
layout(location = 4) in flat uint v_ambient_occlusion;
layout(location = 0) out vec4 f_color;
layout(set = 0, binding = 1) uniform sampler2D block_texture;
void main() {
vec3 ao_color;
switch (v_ambient_occlusion) {
case 0: ao_color = vec3(1.0, 0.0, 0.0); break;
case 1: ao_color = vec3(0.0, 1.0, 0.0); break;
case 2: ao_color = vec3(0.0, 0.0, 1.0); break;
case 3: ao_color = vec3(1.0, 1.0, 1.0); break;
}
f_color = texture(block_texture, v_tex_coord);
f_color.rgb = mix(f_color.rgb, vec3(0.05, 0.05, 0.05), 0.3 * v_ambient_occlusion * distance(v_tile_uv, vec2(0.5)));
}