Sign in to follow this  
Shunyata_Kharg

[SlimDX] A couple of bugs

Recommended Posts

Hello! Just thought I'd report that: LinearGradientBrush does not work as in this example: http://msdn.microsoft.com/en-us/library/dd940321%28VS.85%29.aspx Clipping a region with layers does not work as in this example: http://msdn.microsoft.com/en-us/library/dd756626%28VS.85%29.aspx Thank you!

Share this post


Link to post
Share on other sites
I'm afraid you're going to need to be significantly more specific as to what you mean by "doesn't work" in order for anybody to help you. What does "doesn't work" mean? Doesn't compile? Crashes? Displays unexpected results? What unexpected results? What code did you use? Et cetera.

Share this post


Link to post
Share on other sites
Thanks for your response.

The c#/slimdx code to reproduce the issues can be easily generated from the c++ source files I gave URLs to. If you like I can get some c#/slimdx code for you together, but I thought it would be more useful to the slimdx team to see the original c++ source.

The issues are not crashes. The issues are that the results using slimdx/c# and direct2d api/c++ are not the same. The LinearGradientBrush only draws one color, as the most obvious difference (there are many others) and the clipping example produces an empty (blank) canvas instead of something more visible.

Share this post


Link to post
Share on other sites
Post the code you used to reproduce the behavior; the original C++ code isn't helpful at all, since 90% of SlimDX is just passing parameters directly through to the native code.

Share this post


Link to post
Share on other sites
Yes, I can see by looking at the slimdx source that that is what it's doing. If I was working with the slimdx team I'd be more interested in the original c++ source and trying to replicate the behaviour using c#.

Anyhow, I've reported the issues and will try to upload some c# to this thread when I can.

Share this post


Link to post
Share on other sites
Quote:

If I was working with the slimdx team I'd be more interested in the original c++ source and trying to replicate the behaviour using c#.

I am part of the SlimDX team.

The C++ code isn't helpful: the most likely reason for the behavior is either that there is a bug in the marshaling of one of the parameters to the native code or the invocation of the native function, or that your managed code is passing the wrong thing / making the wrong call / failing to make some other required call. Either way, we need to see the code you are using to identify which managed methods are being used and how.

Share this post


Link to post
Share on other sites
Ok, I would attach a modified SimpleTriangle2D.cs to this message, but I don't think these forums allow that. I will post the code at the end of this message.

I would expect to see a triangle with a vertical gradient in it. Here, the canvas is empty (apart from the back color).

Following the URLs at the beginning of this thread should confirm for you that what I expect to see is not beyond the bounds of reasonable for the direct2d api.

*************
/*
* Copyright (c) 2007-2010 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/


using System.Drawing;

using SlimDX;
using SlimDX.Direct2D;

using SlimDX.SampleFramework;
using System;

namespace SimpleTriangle2D {
/// <summary>
/// Demonstrates how to render a simple colored triangle with Direct2D.
/// </summary>
class SimpleTriangle2DSample : Sample {
/// <summary>
/// Disposes of object resources.
/// </summary>
/// <param name="disposeManagedResources">If true, managed resources should be
/// disposed of in addition to unmanaged resources.</param>
protected override void Dispose(bool disposeManagedResources) {
if (disposeManagedResources) {
brush.Dispose();
geometry.Dispose();
}

base.Dispose(disposeManagedResources);
}

/// <summary>
/// In a derived class, implements logic to initialize the sample.
/// </summary>
protected override void OnInitialize() {
DeviceSettings2D settings = new DeviceSettings2D {
Width = WindowWidth,
Height = WindowHeight
};

InitializeDevice(settings);
geometry = new PathGeometry(Context2D.RenderTarget.Factory);
using (GeometrySink sink = geometry.Open()) {
PointF p0 = new PointF(0.50f * WindowWidth, 0.25f * WindowHeight);
PointF p1 = new PointF(0.75f * WindowWidth, 0.75f * WindowHeight);
PointF p2 = new PointF(0.25f * WindowWidth, 0.75f * WindowHeight);

sink.BeginFigure(p0, FigureBegin.Filled);
sink.AddLine(p1);
sink.AddLine(p2);
sink.EndFigure(FigureEnd.Closed);

// Note that Close() and Dispose() are not equivalent like they are for
// some other IDisposable() objects.
sink.Close();
}

brush = new SolidColorBrush(Context2D.RenderTarget, new Color4(0.93f, 0.40f, 0.08f));
drawRect = new RectangleF(0.25f * WindowWidth, 0.25f * WindowHeight, 0.50f * WindowWidth, 0.50f * WindowHeight);
gBrush = new LinearGradientBrush(Context2D.RenderTarget, GetGradientStops(), GetLinearGradientBrushProperties(drawRect), GetBrushProperties());

layer = new Layer(Context2D.RenderTarget, SizeF.Empty);
layerParams = new LayerParameters();
layerParams.ContentBounds = InfiniteRect();
layerParams.GeometricMask = geometry;

}

private RectangleF InfiniteRect()
{
return RectangleF.FromLTRB(float.MinValue, float.MinValue, float.MaxValue, float.MaxValue);

}


private BrushProperties GetBrushProperties()
{
BrushProperties result = new BrushProperties();

if (transparency == 0)
{
result.Opacity = 1;
}
else
{
result.Opacity = 1 - (transparency / 100.0f);
}

if (gradientAngle > 0)
{
double angle = gradientAngle * (Math.PI / 180.0);

Matrix3x2 matrix = new Matrix3x2();
matrix.M11 = (float)Math.Cos(angle);
matrix.M12 = (float)-Math.Sin(angle);
matrix.M21 = (float)Math.Sin(angle);
matrix.M22 = (float)Math.Cos(angle);
matrix.M31 = 1;
matrix.M32 = 1;

result.Transform = matrix;
}

return result;
}

private LinearGradientBrushProperties GetLinearGradientBrushProperties(RectangleF rect)
{
LinearGradientBrushProperties result = new LinearGradientBrushProperties();
switch (direction)
{
case System.Drawing.Drawing2D.LinearGradientMode.BackwardDiagonal:
result.StartPoint = new PointF(rect.Right, rect.Top);
result.EndPoint = new PointF(rect.Left, rect.Bottom);
break;
case System.Drawing.Drawing2D.LinearGradientMode.ForwardDiagonal:
result.StartPoint = new PointF(rect.Left, rect.Top);
result.EndPoint = new PointF(rect.Right, rect.Bottom);
break;
case System.Drawing.Drawing2D.LinearGradientMode.Horizontal:
result.StartPoint = new PointF(rect.Left, rect.Top + (rect.Height / 2.0f));
result.EndPoint = new PointF(rect.Right, rect.Top + (rect.Height / 2.0f));
break;
case System.Drawing.Drawing2D.LinearGradientMode.Vertical:
result.StartPoint = new PointF(rect.Left + (rect.Width / 2.0f), rect.Top);
result.EndPoint = new PointF(rect.Left + (rect.Width / 2.0f), rect.Bottom);
break;
}

return result;
}

private GradientStopCollection GetGradientStops()
{
GradientStop[] stops;

stops = new GradientStop[3];
stops[0] = new GradientStop();
stops[0].Color = Color.Red;
stops[0].Position = 0.0f;
stops[1] = new GradientStop();
stops[1].Color = Color.White;
stops[1].Position = 0.5f;
stops[2] = new GradientStop();
stops[2].Color = Color.Blue;
stops[2].Position = 1.0f;

return new GradientStopCollection(Context2D.RenderTarget, stops, Gamma.StandardRgb, ExtendMode.Clamp);
}

/// <summary>
/// In a derived class, implements logic that should occur before all
/// other rendering.
/// </summary>
protected override void OnRenderBegin() {
Context2D.RenderTarget.BeginDraw();
Context2D.RenderTarget.Transform = Matrix3x2.Identity;
Context2D.RenderTarget.Clear(new Color4(0.3f, 0.3f, 0.3f));
}

/// <summary>
/// In a derived class, implements logic to render the sample.
/// </summary>
protected override void OnRender() {
Context2D.RenderTarget.PushLayer(layer, layerParams);
Context2D.RenderTarget.FillRectangle(gBrush, drawRect);

}

/// <summary>
/// In a derived class, implements logic that should occur after all
/// other rendering.
/// </summary>
protected override void OnRenderEnd() {
Context2D.RenderTarget.PopLayer();
Context2D.RenderTarget.EndDraw();
}

#region Implementation Detail

PathGeometry geometry;
SolidColorBrush brush;
LinearGradientBrush gBrush;

Layer layer;
LayerParameters layerParams;
RectangleF drawRect;
int transparency = 0;
int gradientAngle = 0;
System.Drawing.Drawing2D.LinearGradientMode direction = System.Drawing.Drawing2D.LinearGradientMode.Vertical;


#endregion
}
}

*************



[Washu] Edit: Please use source boxes.

[Edited by - Shunyata_Kharg on March 12, 2010 2:00:53 AM]

Share this post


Link to post
Share on other sites
Ok, I never used D2D, but I think there is something going wrong with the init of layer.ContentBounds. The InfiniteRect you define is not that infinite, according to RectangleF construction you get a rectangle covering x < 0 and y < 0. float.MinValue + float.MaxValue yields zero, so both Right and Bottom are, too.

Maybe that's why you don't see anything, since "normal screen coords" will be clipped.

Share this post


Link to post
Share on other sites
Quote:
Original post by unbird
Ok, I never used D2D, but I think there is something going wrong with the init of layer.ContentBounds. The InfiniteRect you define is not that infinite, according to RectangleF construction you get a rectangle covering x < 0 and y < 0. float.MinValue + float.MaxValue yields zero, so both Right and Bottom are, too.

Maybe that's why you don't see anything, since "normal screen coords" will be clipped.


Yes, you're right. So I changed it to:


private RectangleF InfiniteRect()
{
return RectangleF.FromLTRB(float.MinValue, float.MinValue, float.MaxValue, float.MaxValue);
}



and it gives the same result. In fact, I can put a completely different value in here, e.g.
layerParams.ContentBounds = new RectangleF(0, 0, WindowWidth, WindowHeight);

and it still gives me the same result, a blank canvas. I do not see this as the cause of the problem.

Share this post


Link to post
Share on other sites
Quote:

I do not see this as the cause of the problem.

You're not initializing the transformations for the brush or the layer, so they remain zero-initialized. Nor are you supplying the opacity for the layer, so it is 0 as well.

Share this post


Link to post
Share on other sites
Quote:
Original post by jpetrie
You're not initializing the transformations for the brush or the layer, so they remain zero-initialized. Nor are you supplying the opacity for the layer, so it is 0 as well.


Perfect, many thanks for your help!

Thank you.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this