Porting from OpenGL to Directx

Started by
29 comments, last by xDarkice 12 years, 3 months ago
Could this issue also be caused because I am not using textures with sizes of a power of two? The Sizes are not the same, they need to get scaled. For instance covers of any size can be used and they need to get scaled to fit. Could my calculation of the positions be too inaccurate? I need to scale the positions down to values from 0 to 1. In OpenGL I was able to specify screen positions. Is there a setting to do this in D3D aswell?

Edit: I got it smooth now. But I am now getting small bars. After setting m_Device.SetSamplerState(0, SamplerState.MinFilter, TextureFilter.Linear);
m_Device.SetSamplerState(0, SamplerState.MagFilter, TextureFilter.Linear);
m_Device.SetSamplerState(0, SamplerState.MipFilter, TextureFilter.Linear);
I do not get the Previewvideo anymore and these small bars are appearing. Any ideas?

Edit2: m_Device.SetSamplerState(0, SamplerState.MipFilter, TextureFilter.Linear); is definetely the line which is breaking the video. Could this be due to I am not filling the video's mipmaps? This is how I am adding a new texture for a video:

public STexture AddTexture(int W, int H, ref byte[] Data)
{
STexture texture = new STexture(-1);
texture.width = W;
texture.height = H;
texture.w2 = texture.width;
texture.h2 = texture.height;
texture.width_ratio = texture.width / texture.w2;
texture.height_ratio = texture.height / texture.h2;
Texture t = new Texture(m_Device, W, H, 0, Usage.Dynamic, Format.A8R8G8B8, Pool.Default);
DataRectangle rect = t.LockRectangle(0, LockFlags.None);
for(int i = 0; i < Data.Length;) {
rect.Data.Write(Data, i, 4 * W);
i+= 4*W;
rect.Data.Position = rect.Data.Position - 4 * W;
rect.Data.Position += rect.Pitch;
}
t.UnlockRectangle(0);
_D3DTextures.Add(t);
texture.index = _D3DTextures.Count - 1;
texture.color = new SColorF(1f, 1f, 1f, 1f);
texture.rect = new SRectF(0f, 0f, texture.width, texture.height, 0f);
texture.TexturePath = String.Empty;
_Textures.Add(texture);
return texture;
}


And this is how I am updating this:

public bool UpdateTexture(ref STexture Texture, ref byte[] Data)
{
if ((Texture.index >= 0) && (_Textures.Count > 0) && (_D3DTextures.Count > Texture.index))
{
DataRectangle rect = _D3DTextures[Texture.index].LockRectangle(0, LockFlags.None);
for (int i = 0; i < rect.Data.Length; )
{
if (rect.Data.Length - rect.Data.Position > 4 * (int)Texture.width)
{
rect.Data.Write(Data, i, 4 * (int)Texture.width);
i += 4 * (int)Texture.width;
rect.Data.Position = rect.Data.Position - 4 * (int)Texture.width;
rect.Data.Position += rect.Pitch;
}
else
break;
}
rect.Data.Position = 0;
_D3DTextures[Texture.index].UnlockRectangle(0);
}
return true;
}


I do not need to use MipMaps for videos due to performance reasons, can I disable MipMaps for single textures only?
Advertisement
Yes, you can disable/enable mip lookup between every draw call. Each draw call uses the state that happens to be set before it.

Niko Suni

Ok, I got this now. Can I force DirectX to use screen positions instead of values from 0 to 1 to set the Z-Positions and the vertexpositions much more precisely?

I think there could be some 'fighting' between the values when they are too near together. In OpenGL I can do this. Ideas?

Edit: I am trying to use this Matrix.OrthoLH(Screenwidth, Screenheight, zNear, zFar); This works, but if I am using screenpositions now for drawing, the textures are shifted to the mid of the screen. Basically, position 0,0 is the center of the screen, but I want it to be at the top left.
You could make a matrix that scales and biases coordinates from 0...screenwidth and 0...screenheight to -1...1. This is very simple math.

Niko Suni

Also, floating point precision is very sufficient for today's display resolutions.

Niko Suni

I got almost everything now, some bugs are left. The biggest one is about resizing the window. In OpenGL I am doing this:

private void RResize()
{
h = control.Height;
w = control.Width;
y = 0;
x = 0;


if ((float)w / (float)h > CSettings.GetRenderAspect())
{
w = (int)Math.Round((float)h * CSettings.GetRenderAspect());
x = (control.Width - w) / 2;
}
else
{
h = (int)Math.Round((float)w / CSettings.GetRenderAspect());
y = (control.Height - h) / 2;
}
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(0, CSettings.iRenderW, CSettings.iRenderH, 0, (double)CSettings.zNear, (double)CSettings.zFar);
GL.Viewport(x, y, w, h);
}


For DirectX i was trying with:
private void RResize()
{
h = this.Height;
w = this.Width;
y = 0;
x = 0;


if ((float)w / (float)h > CSettings.GetRenderAspect())
{
w = (int)Math.Round((float)h * CSettings.GetRenderAspect());
x = (this.Width - w) / 2;
}
else
{
h = (int)Math.Round((float)w / CSettings.GetRenderAspect());
y = (this.Height - h) / 2;
}
if(_Run)
{
m_Device.Viewport= new Viewport(x, y, w, h);
}
}


But I am getting
Direct3D9: (ERROR) :Viewport outside the render target surface

Another one is when I open up the task manager or a UAC window appears, my device is lost. I think I have to call Device.Reset(). After I disposed all objects, i need a way to recreate the textures which are lost in this process. I need help doing this

Edit2: I am still stuck at resizing my window with the correct aspect ratio. If I set the viewport like this it will go out of my window, it is shifted the right way though but the width and height is too big
Can someone give me some tips to increase the performance, especially when much textures are drawn to the screen? I am including my whole source code for my D3D interface. Additionally, this does not work on Intel Graphicscards, I think I am using a mode that Intel graphics cant use, but due to the fact that I got no Intel Graphicscard here, I cant test it with debug runtimes. Does Intel provide a list of supported modes?

http://pastebin.com/QNHABBm5

Edit: I came up with an idea: Could I write all Vertices into a list, which is only rendered once per frame(in my MainLoop) and is discarded after? Is this the way not to lock the VertexBuffer several times a frame? Which size is common for a vertexbuffer? Right now I am using this size 4 * Marshal.SizeOf(typeof(TexturedColoredVertex), which is rather small i think. I heard I can draw several vertices a time, so i would be using a factor of my current size?
I got the performance fixed now, but I am still having issues resizing my window.

Right now I am resizing my viewport but it seems as if the width and height parameters are ignored, the frame will shift by my x and y coordinates but it wont use the width and height i specified so that it is running out of my window.

Do I have to set the backbuffer width and height? Do I have to change something at my orthogonal projection or my translation matrix?
Due to performance causes I need a new way of creating textures from a bitmap. I am currently using this, but due to the fact that I use Bitmap.Save it isnt that fast.


using (MemoryStream stream = new MemoryStream())
{
bmp2.Save(stream, ImageFormat.Png);
stream.Position = 0;
Texture t = Texture.FromStream(_Device, stream, 0, w, h, 0, Usage.None, Format.A8R8G8B8, Pool.Managed, Filter.Default, Filter.Default, 0);
_D3DTextures.Add(t);

}


Unfortunetely there is no Method for Texture.FromBitmap in SlimDx. Can someone help?
I got a problem that the textures are clipped when they reach the edges of the viewport. I am creating my VertexBuffer with the DoNotClip Flag and I am setting the RenderState.Clipping to false. Am I missing another flag?

This topic is closed to new replies.

Advertisement