我正在使用 Vulkan (GTX 980),并且我有这个片段着色器:
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout (location = 0) in vec4 inColor;
layout (location = 0) out vec4 outFragColor;
void main() {
outFragColor = inColor;
gl_FragDepth = gl_FragCoord.z / gl_FragCoord.w;
}
但我注意到深度缓冲区工作不正常,所以我补充说:
if (gl_FragCoord.z == 0) {
discard;
}
果然,什么都没有。即使我在几何着色器中这样做
gl_Position.z = 0.5;
EmitVertex();
gl_FragCoord.z
仍然归零。x、y 和 w 值看起来不错(它们不为零)。如果我根本没有设置gl_FragDepth
,它似乎没有默认任何东西(输出闪烁,所以我假设垃圾值)。
作为参考,这是我的几何着色器。它创建狭窄的圆锥截面来表示矢量场的方向。
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#define FACE_COUNT 16
#define PI 3.14159265
layout (points) in;
layout (triangle_strip, max_vertices = FACE_COUNT * 2 * 3) out;
layout (location = 0) in vec4 inPos[1];
layout (location = 0) out vec4 outColor;
layout (push_constant) uniform constants_t {
mat4x4 world;
mat4x4 projection;
vec4 boundsMin;
vec4 boundsMax;
uvec4 resolution;
float arrowSize;
} constants;
vec4 m(vec4 pos, mat4x4 matrix) {
pos.w = 1.0;
return matrix * pos;
}
vec4 transform(vec3 pos) {
vec4 temp = vec4(pos, 1);
temp = m(temp, constants.world);
temp = m(temp, constants.projection);
return temp;
}
vec3 demux() {
uint temp = gl_PrimitiveIDIn;
float xIndex = mod(temp, constants.resolution.x);
temp /= constants.resolution.x;
float yIndex = mod(temp, constants.resolution.y);
temp /= constants.resolution.y;
float zIndex = temp;
vec3 centeringOffset = vec3(.5);
return (vec3(xIndex, yIndex, zIndex) + centeringOffset) / constants.resolution.xyz * (constants.boundsMax - constants.boundsMin).xyz + constants.boundsMin.xyz;
}
// light a triangle based on surface normal and return color
vec4 light(vec3 a, vec3 b, vec3 c, vec4 color) {
vec3 normal = cross(normalize(b - a), normalize(c - a));
float upness = (normal.y + 1) * 0.5;
float lightenRange = 0.1;
float lighten = max(0, upness - 1 + lightenRange) / lightenRange;
float downness = 1.0 - upness;
float darkenRange = 0.4;
float darken = max(0, downness - 1 + darkenRange) / darkenRange;
return (color + vec4(0.5) * lighten) * (1 - darken * 0.5);
}
void draw(vec3 a, vec3 b, vec3 c, vec4 color) {
outColor = light(a, b, c, color);
gl_Position = transform(a);
EmitVertex();
gl_Position = transform(b);
EmitVertex();
gl_Position = transform(c);
EmitVertex();
EndPrimitive();
}
void main(void)
{
// world position of arrow base
vec3 base = demux();
// direction of arrow
vec3 forward = inPos[0].xyz;
float horizontalLen = length(forward.xz);
// a direction "right" of forward
vec3 right = horizontalLen > 0.00001 ? normalize(vec3(forward.z, 0, -forward.x)) : vec3(1, 0, 0);
// a direction "up" of forward
vec3 up = normalize(cross(forward.xyz, right.xyz));
// world position of arrow tip
vec3 tip = base + forward * constants.arrowSize * 10;
// populate world positions of "rim" vertices
vec3 pos[FACE_COUNT];
for (int i = 0; i < FACE_COUNT; ++i) {
float theta = i * PI * 2 / FACE_COUNT;
pos[i] = base + (up * cos(theta) + right * sin(theta)) * constants.arrowSize;
}
for (int i = 0; i < FACE_COUNT; ++i) {
int j = (i + 1) % FACE_COUNT;
draw(pos[i], pos[j], tip, vec4(1, 0, 0, 1));
draw(pos[j], pos[i], base, vec4(0, 1, 0, 1));
}
}