Create points with a different shape

Tired of squared Point entities? Here there are few tricks to build points with the shape you want.

First solution: using ImageOnly (Label)

An easy solution could be using an ImageOnly with a texture with transparent borders:

Bitmap bmp1 = new Bitmap(@"pointImage.png");
int halfW = bmp1.Size.Width / 2;
int halfH = bmp1.Size.Height / 2;
ImageOnly img = new ImageOnly(10, 20, 0, bmp1, halfW, halfW);
ImageOnly img2 = new ImageOnly(50, 80, 0, bmp1, halfW, halfH);

Second solution: creating a Picture ZoomInvariant

A little bit more complicated solution is to follow the instructions in the Zoom Invariant / Position Invariant Entity article and extend the class Picture initialized with a texture that has the same characteristics described in the previous solution.

Alternative solution (OpenGL only)

There is an alternative solution to the previous ones that is possible to use only with OpenGL renderer.

This shader allows you to use Point Sprites, meaning points that are drawn with a texture always facing the viewer.

This allows drawing points with various shapes, simply providing the point coordinate and a texture.

First define the shader:

class PointSpriteShader : GLShader
{
    private static string vertexCode = @"void main()
    {
        gl_Position = ftransform();
    }";

    private static string fragmentCode = @"
    uniform sampler2D tex;

    void main()
    {
        vec4 finalColor = texture(tex, gl_PointCoord);

        if (finalColor.w == 0)
            discard;
        gl_FragColor = finalColor;
    }
    ";

    public PointSpriteShader() : base(vertexCode, fragmentCode)
    {
    }

    public override void SetParameters(object shaderParams)
    {
        ShaderParametersBase shaderParameters = (ShaderParametersBase)shaderParams;

        Enable(shaderParameters.renderContext);

        gl.Uniform1i(GetUniformLocation("tex"), 0);

        Disable(shaderParameters.renderContext);
    }
}

Then derive the Point class so that it properly sets the shader when it is drawn:

class MyPoint : Point
{
    public GLShader shader;
    public MyPoint(Point3D p) : base(p)
    {
    }

    public TextureBase texture;

    const int GL_POINT_SPRITE = 0x8861;
    const int GL_COORD_REPLACE = 0x8862;

    protected override void DrawForSelection(GfxDrawForSelectionParams data)
    {
        base.Draw(data);
    }

    protected override void Draw(DrawParams data)
    {
        shader.Enable(data.RenderContext);

        data.RenderContext.SetTexture(texture);
        data.RenderContext.PushBlendState();

        // If transparency in the texture is desired, enable the blending
        data.RenderContext.SetState(blendStateType.Blend);

        gl.Enable(GL_POINT_SPRITE);
        gl.TexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, gl.TRUE);

        base.Draw(data);

        gl.Disable(GL_POINT_SPRITE);

        data.RenderContext.CloseTexture();
        data.RenderContext.PopBlendState();

        // Restore the current shader 
        data.RenderContext.SetShader(data.RenderContext.CurrentShader, data.ShaderParams, true);
    }
}

Then create the shader, compile it, create the derived point, assign the shader and a texture:

GLShader myShader = new PointSpriteShader();
bool success = myShader.Compile(model1.renderContext);
if (success)
{
    var texture = new OGLTexture();
    var bmp = new Bitmap(@"star.png");
    texture.Load(model1.renderContext, bmp, textureFilteringFunctionType.Linear);

    var rand = new Random(123);
    for (int i = 0; i < 100; i++)
    {
        var pt = new MyPoint(new Point3D(rand.Next(255), rand.Next(255), rand.Next(255)));

        pt.texture = texture;
        pt.shader = myShader;
        pt.LineWeight = 15;
        pt.LineWeightMethod = colorMethodType.byEntity;

        model1.Entities.Add(pt);
    }

    myShader.SetParameters(new ShaderParameters(model1.renderContext));
}

Result:

Previous versions: Eyeshot 11, Eyeshot 9

Was this article helpful?
0 out of 0 found this helpful
Have more questions? Submit a request

Comments

0 comments

Please sign in to leave a comment.