0

I'm using Vulkan (GTX 980), and I have this fragment shader:

#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;
}

but I noticed that the depth buffer wasn't working quite right, so I added:

if (gl_FragCoord.z == 0) {
    discard;
}

and sure enough, nothing draws. Even if I do this in the geometry shader

gl_Position.z = 0.5;
EmitVertex();

gl_FragCoord.z still comes back as zero. The x, y and w values seem fine (they're non-zero). If I don't set gl_FragDepth at all, it seems to not default to anything (the output flickers, so I'm assuming garbage values).

For reference, this is my geometry shader. It creates narrow conic sections to represent the directions of a vector field.

#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));
    }

}
Brent
  • 4,153
  • 4
  • 30
  • 63
  • FYI: `outColor = light(a, b, c, color);` All GS outputs are invalidated after calling `EmitVertex`. That means that their value is no longer guaranteed. If you want to emit the same output value for multiple vertices, you *must* write it for each vertex. – Nicol Bolas Apr 15 '17 at 22:14
  • Also FYI: `constants_t` is a very large buffer, by push constant standards. Most hardware can only handle push buffers of 128 bytes in size, and that definition exceeds 128 bytes. – Nicol Bolas Apr 15 '17 at 22:18
  • Useful info. Thanks. What would be the proper way to implement the constants without push constants? – Brent Apr 16 '17 at 00:36
  • @Brent as a uniform buffer – ratchet freak Apr 16 '17 at 13:23

0 Answers0