n3b
Topic Author
Posts: 5
Joined: 06 Feb 2024, 17:45

Different matrices in native and managed builds

14 Feb 2024, 17:39

I've been playing with managed build and found out DrawBatch produces matrix with Z axis being transformed into -1..1 range, while native keeps it in 0..1. Is it a recent change or am I missing some configuration option?
Would it make more sense to have viewport matrix exposed rather than doing hidden transformations internally?
 
User avatar
jsantos
Site Admin
Posts: 3925
Joined: 20 Jan 2012, 17:18
Contact:

Re: Different matrices in native and managed builds

15 Feb 2024, 19:07

Although the projection matrix should be always the same for all renderers, a renderer can activate certain flags to change this:
struct DeviceCaps
{
    // Offset in pixel units from top-left corner to center of pixel
    float centerPixelOffset = 0.0f;

    // When this flag is enabled the device works in 'Linear' mode. All internal textures and
    // offscreens are created in 'sRGB' format. In this mode, the device also expects colors
    // (like the ones in the vertex buffer) in 'sRGB' format. It also indicates that the device
    // writes to the render target in linear space
    bool linearRendering = false;

    // This flag is enabled to indicate that the device supports LCD subpixel rendering. Extra
    // shaders and dual source blending are needed for this feature
    bool subpixelRendering = false;

    // Indicates whether the device clip space depth values range from 0 to 1
    bool depthRangeZeroToOne = true;

    // Whether the device clip space Y values are inverted (increase from top (-1) to bottom (1))
    bool clipSpaceYInverted = false;
};
Vulkan renderer is for example enabling clipSpaceYInverted and OpenGL is disabling depthRangeZeroToOne.

This could explain what you are observing. Are you using the same renderer in both native and managed?
 
n3b
Topic Author
Posts: 5
Joined: 06 Feb 2024, 17:45

Re: Different matrices in native and managed builds

16 Feb 2024, 04:09

Oh, thank you, I see the difference now. The .Net DeviceCaps does not have these two:
bool depthRangeZeroToOne = true;
bool clipSpaceYInverted = false;
Sorry I forgot to mention that I use my own custom Vulkan renderer in both cases.

And another question about those matrices - does Noesis keep the same viewport matrix in between BeginOnscreenRender() and BeginOnscreenRender() for all batches?
i.e. can I always expect it to be a transformation from View dimensions to NDC or can it be something else too?
 
User avatar
jsantos
Site Admin
Posts: 3925
Joined: 20 Jan 2012, 17:18
Contact:

Re: Different matrices in native and managed builds

16 Feb 2024, 10:50

Oh, thank you, I see the difference now. The .Net DeviceCaps does not have these two:
Yes, sorry about that. Fixed here. Please add the following at the end of the C# struct
        /// <summary>Indicates whether the device clip space depth values range from 0 to 1</summary>
        [MarshalAs(UnmanagedType.U1)]
        public bool DepthRangeZeroToOne;

        /// <summary>Whether the device clip space Y values are inverted (increase from top (-1) to bottom (1))</summary>
        [MarshalAs(UnmanagedType.U1)]
        public bool ClipSpaceYInverted;
And another question about those matrices - does Noesis keep the same viewport matrix in between BeginOnscreenRender() and BeginOnscreenRender() for all batches?
i.e. can I always expect it to be a transformation from View dimensions to NDC or can it be something else too?
The projection matrix takes your from view space to NDC. The viewport matrix (I assume here what you set in vkCmdSetViewport) must bet set accordingly:
  • In the offscreen phase, this must be set in RenderDevice.SetRenderTarget to the dimensions of the surface.
  • In the onscreen phase, this must be set by you and must be same dimensions as you set in the view (with SetSize)
I hope this makes everything clearer.
 
n3b
Topic Author
Posts: 5
Joined: 06 Feb 2024, 17:45

Re: Different matrices in native and managed builds

24 Feb 2024, 00:58

Thank you.
What I meant is that Noesis internally multiplies the matrix I provide with another one which is not exposed. So I have to pass in it's inverse and MVP to cull in world space, and then to reapply it in DrawBatch in order to make it back to NDC to render to PBR textures.
I'm wondering if that internal matrix is persistent as long as view size is.
 
User avatar
jsantos
Site Admin
Posts: 3925
Joined: 20 Jan 2012, 17:18
Contact:

Re: Different matrices in native and managed builds

26 Feb 2024, 13:46

Yes, the internal matrix only changes with the dimensions of the view.
void VGLContext::SetViewport(const Rect& rect, bool flipY)
{
    mViewport = rect;
    mViewportFlipY = flipY;

    if (IsZero(rect.width) || IsZero(rect.height))
    {
        mBias = Matrix4::Identity();
    }
    else
    {
        float sx = 2.0f / rect.width;
        float sy = 2.0f / rect.height;

        float dx = -sx * rect.x - 1.0f;
        float dy = -sy * rect.y - 1.0f;
        float s = !mClipSpaceYInverted ? (flipY ? -1.0f : 1.0f) : (flipY ? 1.0f : -1.0f);

        float sz = mDepthRangeZeroToOne ? 1.0f : 2.0f;
        float dz = mDepthRangeZeroToOne ? 0.0f : -1.0f;

        mBias = Matrix4
        (
              sx,    0.0f, 0.0f, 0.0f,
            0.0f,  sy * s, 0.0f, 0.0f,
            0.0f,    0.0f,   sz, 0.0f,
              dx,  dy * s,   dz, 1.0f
        );
    }

    mVisibleBox = AABBox2(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
    mBiasHash = GetHashCode(mBias);

    if (mHasProjection)
    {
        mProjectionMatrixBias = mProjectionMatrix * mBias;
        mProjectionHash = GetHashCode(mProjectionMatrixBias);
    }
    else
    {
        mProjectionMatrixBias = mBias;
        mProjectionHash = mBiasHash;
    }
}

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 12 guests