VulkanBot

A Discord Bot that renders GLSL shaders.

Add to Discord View on GitHub

Usage

  1. Invite the bot to a server to add it as a personal app.
  2. Send any message containing one or more GLSL code snippets.
    • GLSL code can be embedded using ```glslcode```
    • The entry point must be main.
    • If only one snippet is supplied, it is assumed to be either a fragmet or a compute shader.
    • The type of shader can be specified by putting it directory before the ```glsl, for example: vert```glsl, frag```glsl, or comp```glsl
  3. Right click the message, go to apps and select either "compute", "render image" or "render video".

Pipeline Layout

For rendering, the vertex input layout of the pipeline is the following:

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texture_coordinates;
layout(location = 2) in vec3 normal;

The output layout of the fragment shader is the following:

layout(location = 0) out vec4 color;

The bot also automatically creates and binds certain descriptor sets based on the type of operation (computation or rendering):

layout(binding = 0) uniform sampler2D texture;
layout(binding = 1) uniform UBO
{
    float time;
    float random;
} constants;

By default the texture is the avatar of the user who invoked the bot.

For compute pipeline, there exists an additional buffer descriptor at layout(set = 1, binding = 0), which can be used to write output data of the compute shader into. Its content will be interpreted as the following types (similar to a C union):

Examples

Wave effect on profile picture using a fragment shader

frag```glsl
#version 450

layout(binding = 1) uniform UBO
{
    float time;
    float random;
} constants;
layout(binding = 0) uniform sampler2D tex;
layout(location = 0) in vec2 inTexCoord;
layout(location = 0) out vec4 outColor;

void main()
{
    outColor = texture(tex, inTexCoord+vec2(0, sin(inTexCoord.x*5+constants.time)/10));
}
```

Compute shader printing "Hello World!"

comp```glsl
#version 450

layout(set = 0, binding = 0) uniform sampler2D tex;
layout(set = 0, binding = 1) uniform UBO
{
    float time;
    float random;
} constants;
layout(set = 1, binding = 0) buffer o
{
    uint data[10];
};

void main()
{
    uint i = 0;
    data[i++] = 0x48;
    data[i++] = 0x65;
    data[i++] = 0x6c;
    data[i++] = 0x6c;
    data[i++] = 0x6f;
    data[i++] = 0x20;
    data[i++] = 0x57;
    data[i++] = 0x6f;
    data[i++] = 0x72;
    data[i++] = 0x6c;
    data[i++] = 0x64;
    data[i++] = 0x21;
}
```

Calculate π using a compute shader

```glsl
#version 450

layout(set = 0, binding = 0) uniform sampler2D tex;
layout(set = 0, binding = 1) uniform UBO
{
    float time;
    float random;
} constants;
layout(set = 1, binding = 0) buffer o
{
    float pi;
};

void main() {
    float f = 0;
    for(int i=0; i<10000000; i++) {
    f += (i%2==0?1:-1)*(1.0/(2*i+1));
    }
    pi = 4*f;
}
```

3D rotation of the avatar using a vertex shader

vert```glsl
#version 450

layout(binding = 1) uniform UBO
{
    float time;
    float random;
} constants;
layout(location = 0) in vec3 inPosition;
layout(location = 0) out vec2 outCoord;

void main()
{
    float ax = constants.time;
    float ay = constants.time;
    float az = constants.time;

    mat3 mx = mat3(1, 0, 0, 0, cos(ax), sin(ax), 0, -sin(ax), cos(ax));
    mat3 my = mat3(cos(ay), 0, -sin(ay), 0, 1, 0, sin(ay), 0, cos(ay));
    mat3 mz = mat3(cos(az), sin(az), 0, -sin(az), cos(az), 0, 0, 0, 1);
    mat3 rotation = mx * my * mz;

    vec3 point = vec3(inPosition.xy, sin(inPosition.x*5)*0.1);
    point = rotation * point;

    mat4 projection = mat4(  2.414,  0.000,  0.000,  0.000,
                                0.000,  2.414,  0.000,  0.000,
                                0.000,  0.000, -1.020,  4.899,
                                0.000,  0.000, -1.000,  5.000);
    vec4 projected = vec4(point, 1.0) * projection;

    gl_Position = projected;
    outCoord = (inPosition.xy + vec2(1.0)) / 2.0;
}
```