Jump to content

Edge outline shader example


Josh
 Share

Recommended Posts

Wait, what is the problem? I can see an outline in your screenshot above, and this code works for me:

#include "UltraEngine.h"
#include "ComponentSystem.h"

using namespace UltraEngine;

int main(int argc, const char* argv[])
{
    //Get the displays
    auto displays = GetDisplays();

    //Create a window
    auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);

    //Create a world
    auto world = CreateWorld();

    //Create a framebuffer
    auto framebuffer = CreateFramebuffer(window);

    //Create a camera
    auto camera = CreateCamera(world);
    camera->SetClearColor(0.125);
    camera->SetFov(70);
    camera->SetPosition(0, 0, -3);

    //Create a light
    auto light = CreateBoxLight(world);
    light->SetRotation(35, 45, 0);
    light->SetRange(-10, 10);

    //Create a box
    auto box = CreateBox(world);

    //------------------------------------------------------------------------------------  
    //------------------------------------------------------------------------------------  

    //Render to texture
    box->SetRenderLayers(1 + 2);
    auto cam2 = CreateCamera(world);
    cam2->SetClearColor(0, 0, 0, 0);
    cam2->SetRenderLayers(2);
    cam2->SetFov(camera->GetFov());
    cam2->SetMatrix(camera->matrix);
    cam2->AddPostEffect(LoadPostEffect("Shaders/Outline.fx"));
    auto sz = framebuffer->GetSize();
    auto texbuffer = CreateTextureBuffer(sz.x, sz.y);
    cam2->SetRenderTarget(texbuffer);

    //Display overlay
    auto sprite = CreateSprite(world, sz.x, sz.y);
    sprite->SetColor(0, 1, 1, 1);
    sprite->SetRenderLayers(4);
    auto mtl = CreateMaterial();
    sprite->SetMaterial(mtl);
    mtl->SetTransparent(true);
    mtl->SetTexture(texbuffer->GetColorAttachment());
    auto cam3 = CreateCamera(world, PROJECTION_ORTHOGRAPHIC);
    cam3->SetClearMode(CLEAR_DEPTH);
    cam3->SetRenderLayers(4);
    cam3->SetPosition(sz.x * 0.5f, sz.y * 0.5f, 0);

    //------------------------------------------------------------------------------------  
    //------------------------------------------------------------------------------------  

    //Main loop
    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        box->Turn(0, 1, 0);

        world->Update();
        world->Render(framebuffer);
    }
    return 0;
}

The edge border is more narrow than I think it was in previous builds, but that can be changed by editing "Source/Shaders/PostEffects/Outline.frag":

const int m = 1;

What am I missing, is the problem the outline color not matching the entity color?

image.thumb.png.83aa3378df92817647bdadfef3412040.png

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

It will work if you just lower-case the word "posteffect" in the FX file. This is not your fault, the properties used to be camel-cased during beta testing.

{
  "posteffect": {
    "buffers": [
      {
        "size": [ 0.25, 0.25 ]
      }
    ],
    "subpasses": [
      {
        "samplers": [ "DEPTH", "PREVPASS" ],
        "shader": {
          "float32": {
            "fragment": "Shaders/Outline.frag.spv"
          }
        }
      }
    ]
  }
}

 

  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

  • 3 months later...

Something wrong in latest beta updates again. Color is black instead of entity color:

image.png.d249e45aa0aa0fe2b0308c6e646b9899.png

Also strange bottom edge, same with usual outline (color works tho for usual outline)

Definitely used to work at 17 March but idk which exactly update changed it. Felt something wrong in my game last few days but noticed only now what's wrong.

#include "UltraEngine.h"
#include "ComponentSystem.h"

using namespace UltraEngine;

int main(int argc, const char* argv[])
{
    //Get the displays
    auto displays = GetDisplays();

    //Create a window
    auto window = CreateWindow("Ultra Engine", 0, 0, 1200, 800, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);

    //Create a world
    auto world = CreateWorld();

    //Create a framebuffer
    auto framebuffer = CreateFramebuffer(window);

    //Create a camera
    auto camera = CreateCamera(world);
    camera->SetClearColor(0.125);
    camera->SetFov(70);
    camera->SetPosition(0, 0, -3);

    //Create a light
    auto light = CreateBoxLight(world);
    light->SetRotation(35, 45, 0);
    light->SetRange(-10, 10);

    //Create a box
    auto box = CreateBox(world);
    box->SetColor(1, 0, 0);
    auto outlineBox = CreateBox(world);
    outlineBox->SetColor(0, 1, 0);

    auto material = CreateMaterial();
    auto unlitShader = LoadShaderFamily("Shaders/Unlit.fam");
    material->SetShaderFamily(unlitShader);
    outlineBox->SetMaterial(material);

    //Create a box2 
    auto box2 = CreateBox(world);
    box2->SetColor(1, 0, 0);
    auto outlineBox2 = CreateBox(world);
    outlineBox2->SetColor(0, 0, 1);

    auto material2 = CreateMaterial();
    auto unlitShader2 = LoadShaderFamily("Shaders/Unlit.fam");
    material2->SetShaderFamily(unlitShader);
    outlineBox2->SetMaterial(material);

    outlineBox2->SetPosition(2, 0, 0);
    box2->SetPosition(2, 0, 0);

    //Entity component system
    auto component = box->AddComponent<Mover>();
    component->rotationspeed.y = 45;

    auto outlineComponent = outlineBox->AddComponent<Mover>();
    outlineComponent->rotationspeed.y = 45;

    auto component2 = box2->AddComponent<Mover>();
    component2->rotationspeed.y = 45;

    auto outlineComponent2 = outlineBox2->AddComponent<Mover>();
    outlineComponent2->rotationspeed.y = 45;

    //------------------------------------------------------------------------------------  
    //------------------------------------------------------------------------------------  

    //Render to texture
    outlineBox->SetRenderLayers(2);
    outlineBox2->SetRenderLayers(2);

    auto cam2 = CreateCamera(world);
    cam2->SetClearColor(0, 0, 0, 0);
    cam2->SetRenderLayers(2);
    cam2->SetFov(camera->GetFov());
    cam2->SetMatrix(camera->matrix);
    cam2->AddPostEffect(LoadPostEffect("Shaders/MultipleOutlines.fx"));

    auto sz = framebuffer->GetSize();
    auto texbuffer = CreateTextureBuffer(sz.x, sz.y);
    cam2->SetRenderTarget(texbuffer);

    ////Display overlay
    auto sprite = CreateSprite(world, sz.x, sz.y);
    sprite->SetRenderLayers(4);
    auto mtl = CreateMaterial();
    sprite->SetMaterial(mtl);
    mtl->SetTransparent(true);
    mtl->SetTexture(texbuffer->GetColorAttachment());
    auto cam3 = CreateCamera(world, PROJECTION_ORTHOGRAPHIC);
    cam3->SetClearMode(CLEAR_DEPTH);
    cam3->SetRenderLayers(4);
    cam3->SetPosition(sz.x * 0.5f, sz.y * 0.5f, 0);


    //------------------------------------------------------------------------------------  
    //------------------------------------------------------------------------------------  

    //Main loop
    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        world->Update();
        world->Render(framebuffer, false);
    }
    return 0;
}

MultipleOutlines.frag:

#version 450
#extension GL_ARB_separate_shader_objects : enable
#define UNIFORMSTARTINDEX 1
#include "../Base/CameraInfo.glsl"
#include "../Utilities/Dither.glsl"
#include "../Utilities/DepthFunctions.glsl"

layout(location = 0) out vec4 outColor;

// Uniforms
layout(location = 20, binding = 0) uniform sampler2DMS DepthBuffer;
layout(location = 24) uniform int Thickness = 3; // should be an odd number
layout(binding = 1) uniform sampler2DMS ColorBuffer;

void main()
{
    ivec2 coord = ivec2(gl_FragCoord.x, gl_FragCoord.y);
    outColor = texelFetch(ColorBuffer, coord, gl_SampleID);
    outColor.a = 0.0f;
    float depth = texelFetch(DepthBuffer, coord, gl_SampleID).r;
    //Handle selected objects
    if (depth < 1.0f)
    {
        const int m = max(0, (Thickness - 1) / 2);
        vec2 pixelsize = vec2(1.0f) / BufferSize;

        for (int x = -m; x <= m; ++x)
        {
            for (int y = -m; y <= m; ++y)
            {
                if (x == 0 && y == 0) continue;
                float neighbour = texelFetch(DepthBuffer, coord + ivec2(x, y), gl_SampleID).r;

                if (neighbour == 1.0f)
                {
                    outColor = texelFetch(ColorBuffer, coord, gl_SampleID);
                    return;
                }
            }
        }
    }
}

MultipleOutlines.fx

{
  "posteffect": {
    "buffers": [
      {
        "size": [ 0.25, 0.25 ]
      }
    ],
    "subpasses": [
      {
        "samplers": [ "DEPTH", "PREVPASS" ],
        "shader": {
          "float32": {
            "fragment": "Shaders/PostEffects/MultipleOutlines.frag"
          }
        }
      }
    ]
  }
}

 

Link to comment
Share on other sites

  • 2 weeks later...

Fxied MultipleOutlines.frag:

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform sampler2DMS DepthBuffer;
layout(binding = 1) uniform sampler2D ColorBuffer;

uniform int Thickness = 5;

#include "../Base/CameraInfo.glsl"
#include "../Utilities/Dither.glsl"
#include "../Utilities/DepthFunctions.glsl"

layout(location = 0) out vec4 outColor;

void main()
{
    ivec2 coord = ivec2(gl_FragCoord.x, gl_FragCoord.y);
	outColor = vec4(0.0f);
    int count = textureSamples(DepthBuffer);
    float depth;
    //Handle selected objects
	for (int n = 0; n < count; ++n)
	{
		depth = texelFetch(DepthBuffer, coord, n).r;
		if (depth < 1.0f)
		{
			const int m = max(0, (Thickness - 1) / 2);
			vec2 pixelsize = vec2(1.0f) / BufferSize;

			for (int x = -m; x <= m; ++x)
			{
				for (int y = -m; y <= m; ++y)
				{
					if (x == 0 && y == 0) continue;
					float neighbour = texelFetch(DepthBuffer, coord + ivec2(x, y), n).r;

					if (neighbour == 1.0f)
					{
						outColor += texelFetch(ColorBuffer, coord, gl_SampleID);
						break;
					}
				}
			}
		}
	}
	outColor /= float(count);
}

 

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...