Drawing over a 3D rendered scene using C#

爷,独闯天下 提交于 2019-12-12 03:33:20

问题


UPDATE: Since originally asking this question, I have changed my approach slightly. Rather than drawing using System.Drawing.Graphics, I am hosting a WPF user control with an InkCanvas. That does everything I need it to do. The problem still is that I cannot get the background of the ElementHost to be transparent. I see the same black square I was seeing before.

ORIGINAL QUESTION: I have a C# WinForms application that renders a 3D scene using Ogre3D to a panel in the form using that panel's handle. I am trying to add the ability to draw on top of that scene (imagine Madden drawing over the TV screen) using C#'s System.Drawing.Graphics.

I'm using the BufferedGraphics class to do this. As a test, I'm trying to simply draw a rectangle on top of the 3D scene. Below is a snippet of the code I'm using to set everything up.

namespace TestApp
{
    public partial class TestForm
    {
        private BufferedGraphics graphicsBuffer;
        private BufferedGraphicsContext bufferContext = BufferedGraphicsManager.Current;

        public TestForm()
        {
            InitializeComponent();
            UpdateGraphicsBuffer();
        }

        private void UpdateGraphicsBuffer()
        {
            bufferContext.MaximumBuffer = new Size(panelRender.Width + 1, panelRender.Height + 1);
            graphicsBuffer = bufferContext.Allocate(Graphics.FromHwnd(panelRender.Handle), new Rectangle(49, 49, 100, 100));
            graphicsBuffer.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        }

        private void TestForm_Load(object sender, EventArgs e)
        {
            graphicsBuffer.Graphics.DrawRectangle(new Pen(Color.Red), 50, 50, 50, 50);
        }
    }
}

I've left out a lot of the proprietary code (there is a call to graphicsBuffer.Render(); in part of that proprietary code) and renamed some stuff but hopefully what I have provided will give you the gist. Also, the 3D scene is also using panelRender.Handle to draw into that panel, and the panelRender.BackColor is black.

In a nutshell, what I am seeing is a chunk of my 3D scene missing (specifically a 100x100 chunk) with the 50x50 red rectangle drawn inside it, as pictured here:

Obviously I don't want to lose the scene that I'm trying to draw on top of. Right now, I'm at a loss as to why this is happening. Is what I'm trying to do just not possible? If any additional information/code is needed, I will be happy to provide it, if possible.

EDIT: To try and simplify matters, I created a really simple WinForms app that has a single panel and used the code above to recreate the issue. The code-behind for that is here:

using System.Drawing;
using System.Windows.Forms;

namespace DoubleBufferTest
{
    public partial class Form1 : Form
    {
        private BufferedGraphics graphicsBuffer = null;
        private BufferedGraphicsContext bufferContext = BufferedGraphicsManager.Current;

        public Form1()
        {
            this.SetStyle(ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
            this.UpdateStyles();
            InitializeComponent();
            UpdateGraphicsBuffer();
        }

        private void UpdateGraphicsBuffer()
        {
            bufferContext.MaximumBuffer = new Size(panel1.Width + 1, panel1.Height + 1);
            graphicsBuffer = bufferContext.Allocate(Graphics.FromHwnd(panel1.Handle), new Rectangle(10, 10, 50, 50));
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            graphicsBuffer.Graphics.DrawRectangle(new Pen(Color.Red, 3.0f), 20, 20, 10, 10);
            graphicsBuffer.Render();
        }
    }
}

The panel's backcolor is set to transparent. Here is the result:

That black square corresponds to the graphics buffer that is getting allocated by the context. Why it always shows up as black is basically what is confusing me now...


回答1:


What I think you should do is use the SetStyle method to set the background to transparent. More info at https://msdn.microsoft.com/en-us/library/system.windows.forms.control.setstyle%28v=vs.110%29.aspx




回答2:


Thank you to @Ron Beyer for answering this for me in a different question I posted.

So I was on the right track with the ElementHost control, but because of the transparency issues, Ron suggested that I try using a new WPF window that I could overlay on top of the application (link). The WPF window's background is set to transparent, so drawing on the InkCanvas results in the desired effect.



来源:https://stackoverflow.com/questions/30508405/drawing-over-a-3d-rendered-scene-using-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!