synvael/assets/shaders/cube.vert

56 lines
2.6 KiB
GLSL

#version 450
layout(location = 0) in vec3 in_position;
layout(location = 1) in vec3 in_color;
layout(location = 2) in uint in_face;
layout(location = 0) out vec3 frag_color;
layout(location = 1) out vec3 frag_normal;
layout(location = 2) out float frag_debug_tint;
layout(location = 3) out vec3 frag_world_position;
// The block is declared identically in cube.frag. A push-constant block is a single object shared by every stage of the pipeline, so the two declarations must agree exactly even where a stage reads only part of it.
layout(push_constant) uniform PushConstants {
mat4 mvp;
// xyz is the chunk's world offset; w is the debug-tint weight, 0.0 for normal rendering and 1.0 for a debug raster pass.
vec4 chunk_offset;
// xyz is the camera's world position; w is the horizontal distance at which fog reaches full opacity.
vec4 fog;
// rgb is the sky colour distant geometry fades into, matching the colour attachment's clear value; w is the vertical distance at which fog reaches full opacity.
vec4 sky_color;
} push_constants;
// Size, in pixels, of the points emitted under VK_POLYGON_MODE_POINT. Sizes above 1.0 require the largePoints device feature.
const float DEBUG_POINT_SIZE = 5.0;
// Outward normals of the six cubic face directions, indexed by the packed face attribute.
const vec3 FACE_NORMALS[6] = vec3[6](
vec3( 1.0, 0.0, 0.0),
vec3(-1.0, 0.0, 0.0),
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, -1.0, 0.0),
vec3( 0.0, 0.0, 1.0),
vec3( 0.0, 0.0, -1.0)
);
void main() {
// The chunk-local vertex is shifted into world space by the per-chunk offset before projection.
vec3 world_position = in_position + push_constants.chunk_offset.xyz;
gl_Position = push_constants.mvp * vec4(world_position, 1.0);
// Point size is consulted whenever the polygon mode is POINT; leaving it unwritten renders points of undefined size. It is ignored by the FILL and LINE pipelines, so it is written unconditionally.
gl_PointSize = DEBUG_POINT_SIZE;
frag_color = in_color;
// Chunk placement is a pure translation, so a chunk-local face normal is already a world-space normal and no normal matrix is required.
frag_normal = FACE_NORMALS[in_face];
// Shading and the debug tint both resolve in the fragment stage, so the weight is forwarded rather than applied here.
frag_debug_tint = push_constants.chunk_offset.w;
// Forwarded for the fog term, which needs the distance from the camera to the shaded surface. Interpolating the world position is correct here because it is an affine function of the vertex positions.
frag_world_position = world_position;
}