opentk / GLWpfControl

A fast native control for OpenTK 4.x + 3.x on WPF.
MIT License
201 stars 49 forks source link

FBO Status is FramebufferIncompleteAttachment after render done, in nvidia graphics cards #101

Closed caojingwen1996 closed 6 months ago

caojingwen1996 commented 1 year ago

in nvidia card:

image in intel card:

image here is my code,just copy from source code:

<Window
    x:Class="Example.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:glWpfControl="clr-namespace:OpenTK.Wpf;assembly=GLWpfControl"
    mc:Ignorable="d"
    Title="MainWindow"
    Width="800"
    Height="800">
    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition Height="67*"/>
            <RowDefinition Height="718*"/>
        </Grid.RowDefinitions>

        <glWpfControl:GLWpfControl   Grid.Row="1"
            x:Name="OpenTkControl"
            KeyDown="OpenTkControl_KeyDown"
           MouseUp="OpenTkControl_MouseUp"
                                    MouseDown="OpenTkControl_MouseDown"
             />

    </Grid>
</Window>

MainWindow .cs

 public sealed partial class MainWindow {
        private MousePosRecord _mouseDarg;

        public MainWindow() {
            InitializeComponent();
            var mainSettings = new GLWpfControlSettings {MajorVersion=2,MinorVersion=1, RenderContinuously = false };
            OpenTkControl.Start(mainSettings);

            OpenTkControl.Render += OpenTkControl_OnRender;
            OpenTkControl.SizeChanged += OpenTkControl_SizeChanged;
        }

        private void OpenTkControl_OnRender(TimeSpan delta) {

            ExampleScene.Render();
        }

        private void OpenTkControl_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("wpfcontrol is mouseup");
            int f = -1;
            GL.GetInteger(GetPName.FramebufferBinding, out f);
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, OpenTkControl.Framebuffer);
            var a = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
            var b = GL.GetError();
            float[,] testz = new float[OpenTkControl.FrameBufferWidth, OpenTkControl.FrameBufferHeight];
            GL.ReadPixels(0, 0, OpenTkControl.FrameBufferWidth, OpenTkControl.FrameBufferHeight, PixelFormat.DepthComponent, PixelType.Float, testz);
            var r = GL.GetString(StringName.Renderer);

            GL.GetFramebufferAttachmentParameter(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, FramebufferParameterName.FramebufferAttachmentObjectName, out var nts);
        }

        private void OpenTkControl_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("wpfcontrol is mousedown");
        }
}

ExampleScene .cs

 public static class ExampleScene {
        public static void Render(float alpha = 1.0f) {
            GL.UseProgram(0);

            var hue = (float) _stopwatch.Elapsed.TotalSeconds * 0.15f % 1;
            var c = Color4.FromHsv(new Vector4(alpha * hue, alpha * 0.75f, alpha * 0.75f, alpha));
            GL.ClearColor(c);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            GL.Enable(EnableCap.DepthTest);
            GL.LoadIdentity();
            GL.Begin(PrimitiveType.Triangles);

            GL.Color4(Color4.Red);
            GL.Vertex3(-0.5f, -0.5f,0f);
            GL.Color4(Color4.Green);
            GL.Vertex3(0.5f, -0.5f, 1f);
            GL.Color4(Color4.Blue);
            GL.Vertex3(0.0f, 0.5f, 1f);
            GL.End();
            GL.Finish();
        }
}
NogginBops commented 1 year ago

Can you provide the code you use to create the framebuffer?

caojingwen1996 commented 1 year ago

thank you very much for your replay. I have added relevant codes。here is my test result: 1.Under all frameworks, can not read depth or color from FBO in nvidia graphics cards,but no problem with integrated graphics card

  1. .net5 .net6 .net core ,In the render function, use GL.BlitFramebuffer to copy to the default FBO of opengl (that is, 0), then you can read data from the default fbo (0) . it is not ok under .net framework 4.
NogginBops commented 6 months ago

I see what is happening now. You are calling OpenGL functions that read from the control framebuffer in MouseUp(), this will not work as these resources are only valid inside of Render() because of DirectX interop reasons. So if you want to read from the GLWpfControl framebuffer you will have to do what inside of Render().