Untiy Native Render Plugin在VR中的绘制

本文介绍了如何将Unity的Native Render Plugin应用于VR环境中进行世界空间的绘制。在D3D11示例中,由于DirectX Math已采用行主序,因此无需转置矩阵。C#脚本需要调整投影矩阵,并将其挂载到Camera上,OnPostRender会在每个眼睛上调用两次。此外,还可以从视图矩阵中获取眼睛位置。

官方的NativeRenderPlugin Sample只是画了一个屏幕空间的三角形, 怎么改成世界空间的呢? 以D3D11为例:

Native:

struct ConstantBuffer
{
    DirectX::XMMATRIX World;
    DirectX::XMMATRIX View;
    DirectX::XMMATRIX Projection;
} g_CB;
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SetCameraMatrix(float vm[], float pm[])
{
    g_CB.View = XMLoadFloat4x4(&DirectX::XMFLOAT4X4(vm));
    g_CB.Projection = XMLoadFloat4x4(&DirectX::XMFLOAT4X4(pm));
}

由于DirectX Math已经是row major的, 所以不用转置了.
Shader:

cbuffer MyCB : register(b0) 
{
    float4x4 worldMatrix;
    float4x4 viewMatrix;
    float4x4 projectionMatrix;
}
void VS (float3 pos : POSITION, float4 color : COLOR, out float4 ocolor : COLOR, out float4 opos : SV_Position) 
{
    opos = mul(float4(pos, 1), worldMatrix);
    opos = mul(opos, viewMatrix);
    opos = mul(opos, projectionMatrix);

    ocolor = color;
}

C#脚本这边有个细节, 就是投影矩阵需要转换一下, 不能直接取相机的:

    [DllImport("RenderingPlugin")]
    private static extern void SetCameraMatrix(float[] viewMatrix, float[] projectionMatrix);
    private static float[] MatrixToArray(Matrix4x4 _matrix)
    {
        float[] result = new float[16];

        for (int _row = 0; _row < 4; _row++)
        {
            for (int _col = 0; _col < 4; _col++)
            {
                result[_col + _row * 4] = _matrix[_row, _col];
            }
        }

        return result;
    }

    void OnPostRender()
    {
        // Set time for the plugin
        SetTimeFromUnity(Time.timeSinceLevelLoad);
        if (Camera.current != null)
        {
            var viewMatrix = Camera.current.worldToCameraMatrix;
            var projectionMatrix = GL.GetGPUProjectionMatrix(Camera.current.projectionMatrix, VRSettings.enabled);

            SetCameraMatrix(MatrixToArray(viewMatrix), MatrixToArray(projectionMatrix));
        }

        // Issue a plugin event with arbitrary integer identifier.
        // The plugin can distinguish between different
        // things it needs to do based on this ID.
        // For our simple plugin, it does not matter which ID we pass here.
        GL.IssuePluginEvent(GetRenderEventFunc(), 1);
    }

这个脚本挂到Camera上即可, OnPostRender会分别针对左右眼调用两次, 所以Native那边会产生两次绘制.
另外, Native这边也可以从视图矩阵中还原出眼睛位置:

        XMMATRIX invViewMatrix = XMMatrixInverse(nullptr, g_CB.View);
        XMVECTOR eyePos = XMMatrixTranspose(invViewMatrix).r[3];

参考资料

http://forum.unity3d.com/threads/native-c-plugin-in-world-space.196512/
https://github.com/obviousjim/ofxUnity/blob/master/UnityProject/Assets/UseRenderingPlugin.cs
http://docs.unity3d.com/ScriptReference/Camera-projectionMatrix.html
http://docs.unity3d.com/ScriptReference/Camera.Render.html
https://forums.oculus.com/community/discussion/16313/native-rendering-plugin-with-oculus-rift
http://forum.unity3d.com/threads/different-content-in-each-eye.332575/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值