Help with rendering backgroud.

Tsmit42

Newcomer
OK I know this is completely a newbie question, but I can't figure this out for anything. I have a SplashScreen class and it rendering looks off for some reason.

this is the SplashScreen class.
Code:
public class SplashScreen : IDisposable
    {
        private Device m_Device;
        private Image m_Image = null;
        private DateTime m_StartTime;
        private DateTime m_EndTime = DateTime.Now;
        private VertexBuffer m_VertexBuffer;
        private bool m_Initialized = false;
        private TimeSpan m_TimeLeft;
        private CustomVertex.TransformedTextured[] m_VertexData;

        public SplashScreen(Device _Device, string _Filename, byte _Duration )
        {
            this.m_Device = _Device;
            this.m_Image = new Image(this.m_Device, _Filename);
            this.m_StartTime = DateTime.Now;
            this.m_EndTime = DateTime.Now.AddSeconds(_Duration);
            this.m_VertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedTextured), 4, this.m_Device, Usage.WriteOnly, CustomVertex.TransformedTextured.Format, Pool.Default);
        }

        public bool Render()
        {
            try
            {
                bool FogState = this.m_Device.RenderState.FogEnable;
                this.m_Device.RenderState.FogEnable = false;

                this.m_VertexData = new CustomVertex.TransformedTextured[4];
                this.m_VertexData[0].X = 0.0f;
                this.m_VertexData[0].Y = 0.0f;
                this.m_VertexData[0].Z = 1.0f;
                this.m_VertexData[0].Tu = 0.0f;
                this.m_VertexData[0].Tv = 0.0f;
                this.m_VertexData[1].X = this.m_Device.Viewport.Width;
                this.m_VertexData[1].Y = 0.0f;
                this.m_VertexData[1].Z = 1.0f;
                this.m_VertexData[1].Tu = 1.0f;
                this.m_VertexData[1].Tv = 0.0f;
                this.m_VertexData[2].X = 0.0f;
                this.m_VertexData[2].Y = this.m_Device.Viewport.Height;
                this.m_VertexData[2].Z = 1.0f;
                this.m_VertexData[2].Tu = 0.0f;
                this.m_VertexData[2].Tv = 1.0f;
                this.m_VertexData[3].X = this.m_Device.Viewport.Width;
                this.m_VertexData[3].Y = this.m_Device.Viewport.Height;
                this.m_VertexData[3].Z = 1.0f;
                this.m_VertexData[3].Tu = 1.0f;
                this.m_VertexData[3].Tv = 1.0f;

                this.m_VertexBuffer.SetData(this.m_VertexData, 0, 0);
                this.m_Device.SetStreamSource(0, this.m_VertexBuffer, 0);
                this.m_Device.VertexFormat = CustomVertex.TransformedTextured.Format;
                this.m_Device.SetTexture(0, this.m_Image.Texture);
                this.m_Device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
                this.m_Device.RenderState.FogEnable = FogState;
            }
            catch(DirectXException Error)
            {
                Console.AddLine("Unable to display splash screen.");
                Console.AddLine(Error.ErrorString);
            }
            catch(Exception Error)
            {
                Console.AddLine("Unable to display splash screen.");
                Console.AddLine(Error.Message);
            }

            DateTime CurrentTime = DateTime.Now;
            return (CurrentTime > this.m_EndTime);
        }

        public bool Initialized
        {
            get { return this.m_Initialized; }
            set { this.m_Initialized = value; }
        }

        public TimeSpan TimeLeft
        {
            get { return this.m_TimeLeft; }
            set { this.m_TimeLeft = value; }
        }

        public void Dispose()
        {
            this.m_Image.Dispose();
        }

        public void Restore()
        {
            if (this.m_Image != null)
            {
                this.m_Image.Load();
            }
        }
    }


this is the original


and this is the how it is rendered.
[/img]
 
you have to take into acount the subpixel offset. What your seeing is the bilinear filter dealing with the 0.5 offsets.

If I remember correctly the center of the pixel is at 0,0, so you need to offset the screent coordinates by 0.5 pixels left and up.

Having said that last time I looked you could still set the pixel offset in the nvidia drivers, although I assume the default correlates with whatever the current standard is.

Just turning on points ampling would probably also be enough to fix it.
 
You should still do subpixel shifting even when point sampling. Over a large screensize you can get small floating point errors occuring and the pointsampling ends up 'doubling' pixels where it shouldn't.
 
Ok thanks for the help guys, but I searched google for pixel shifting and point sampling but couldn't find anything useful. Could you point me in the direction of some articles that would help me out on this subject?
 
Ok, I changed my render function to this.

Code:
public bool Render()
        {
            try
            {
                bool FogState = this.m_Device.RenderState.FogEnable;
                this.m_Device.RenderState.FogEnable = false;
                float OffSet = 0.5f;

                this.m_VertexData = new CustomVertex.TransformedTextured[4];
                this.m_VertexData[0].X = 0.0f + OffSet;
                this.m_VertexData[0].Y = 0.0f + OffSet;
                this.m_VertexData[0].Z = 1.0f;
                this.m_VertexData[0].Tu = 0.0f;
                this.m_VertexData[0].Tv = 0.0f;
                this.m_VertexData[1].X = (float)this.m_Device.Viewport.Width + OffSet;
                this.m_VertexData[1].Y = 0.0f + OffSet;
                this.m_VertexData[1].Z = 1.0f;
                this.m_VertexData[1].Tu = 1.0f;
                this.m_VertexData[1].Tv = 0.0f;
                this.m_VertexData[2].X = 0.0f + OffSet;
                this.m_VertexData[2].Y = (float)this.m_Device.Viewport.Height + OffSet;
                this.m_VertexData[2].Z = 1.0f;
                this.m_VertexData[2].Tu = 0.0f;
                this.m_VertexData[2].Tv = 1.0f;
                this.m_VertexData[3].X = (float)this.m_Device.Viewport.Width + OffSet;
                this.m_VertexData[3].Y = (float)this.m_Device.Viewport.Height + OffSet;
                this.m_VertexData[3].Z = 1.0f;
                this.m_VertexData[3].Tu = 1.0f;
                this.m_VertexData[3].Tv = 1.0f;
                this.m_VertexBuffer.SetData(this.m_VertexData, 0, 0);
                this.m_Device.SetStreamSource(0, this.m_VertexBuffer, 0);
                this.m_Device.VertexFormat = CustomVertex.TransformedTextured.Format;
                this.m_Device.SetTexture(0, this.m_Image.Texture);
                this.m_Device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
                this.m_Device.RenderState.FogEnable = FogState;
            }
            catch(DirectXException Error)
            {
                Console.AddLine("Unable to display splash screen.");
                Console.AddLine(Error.ErrorString);
            }
            catch(Exception Error)
            {
                Console.AddLine("Unable to display splash screen.");
                Console.AddLine(Error.Message);
            }

            DateTime CurrentTime = DateTime.Now;
            return (CurrentTime > this.m_EndTime);
        }

But now it renders part of the screen correctly but other parts are still the same.
 
you may want to avoid the viewvolume/viewport clipping logic, as it may introduce extra error in your carefully-calculated offsets. i.e. make sure the quad you draw does not get clipped: set the right-most and bottom-most coords (if your y grows downwards) to Viewport.Width - 1 + OffSet and Viewport.Height - 1 + OffSet, respectively.
 
I think I got it to work like it was intended, but the picture quality is not what I was looking for. So I was wondering, would directdraw give me better picture quality for just displaying a simple image on the screen? or am I still doing something wrong and it should work the same with direct3d? And can I use directdraw for splashscreen rendering and do the rest in direct3d?
 
Yes i set it to point, here is the final render code below. However it looks ok with a regular image, but the screenshot of my desktop you can see the artifacts because of the text I guess. While this would probably work great for most purposes, I just wanted to get close to a 1:1 as possible.

Code:
public bool Render()
        {
            try
            {
                bool FogState = this.m_Device.RenderState.FogEnable;
                this.m_Device.RenderState.FogEnable = false;
                this.m_Device.SamplerState[0].MagFilter = TextureFilter.Point;
                this.m_Device.SamplerState[0].MinFilter = TextureFilter.Point;
                this.m_Device.SamplerState[0].MipFilter = TextureFilter.Point;
                float OffSet = 0.5f;

                this.m_VertexData = new CustomVertex.TransformedTextured[4];
                this.m_VertexData[0].X = 0.0f - OffSet;
                this.m_VertexData[0].Y = 0.0f + OffSet;
                this.m_VertexData[0].Z = 1.0f;
                this.m_VertexData[0].Tu = 0.0f;
                this.m_VertexData[0].Tv = 0.0f;
                this.m_VertexData[1].X = (float)1024;
                this.m_VertexData[1].Y = 0.0f + OffSet;
                this.m_VertexData[1].Z = 1.0f;
                this.m_VertexData[1].Tu = 1.0f;
                this.m_VertexData[1].Tv = 0.0f;
                this.m_VertexData[2].X = 0.0f - OffSet;
                this.m_VertexData[2].Y = (float)768;
                this.m_VertexData[2].Z = 1.0f;
                this.m_VertexData[2].Tu = 0.0f;
                this.m_VertexData[2].Tv = 1.0f;
                this.m_VertexData[3].X = (float)1024;
                this.m_VertexData[3].Y = (float)768;
                this.m_VertexData[3].Z = 1.0f;
                this.m_VertexData[3].Tu = 1.0f;
                this.m_VertexData[3].Tv = 1.0f;

                this.m_VertexBuffer.SetData(this.m_VertexData, 0, 0);
                this.m_Device.SetStreamSource(0, this.m_VertexBuffer, 0);
                this.m_Device.VertexFormat = CustomVertex.TransformedTextured.Format;
                this.m_Device.SetTexture(0, this.m_Image.Texture);
                this.m_Device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
                this.m_Device.RenderState.FogEnable = FogState;
            }
            catch(DirectXException Error)
            {
                Console.AddLine("Unable to display splash screen.");
                Console.AddLine(Error.ErrorString);
            }
            catch(Exception Error)
            {
                Console.AddLine("Unable to display splash screen.");
                Console.AddLine(Error.Message);
            }

            DateTime CurrentTime = DateTime.Now;
            return (CurrentTime > this.m_EndTime);
        }

final image
 
Play around with the offsets, Assumiong you have AA and texture filter overides disabled in your control panel you should be able to get an exact 1 to 1 mapping.
 
Well I have intel intergrated graphics(Don't laugh), so I don't think there is a place where I can set AA and filtering. I have played around with every possible offset combination and the final code is the best looking one.

However the only offset value I tried is 0.5f, is that the only possible one that would work? or are there aother values that might work? Maybe there is something outside the render code that I need to set/change to make it work?
 
try this

Code:
public bool Render()
{
        // other code snipped

        this.m_VertexData[0].X = 0.0f - OffSet;
        this.m_VertexData[0].Y = 0.0f + OffSet;
        this.m_VertexData[0].Z = 1.0f;
        this.m_VertexData[0].Tu = 0.0f;
        this.m_VertexData[0].Tv = 0.0f;
        this.m_VertexData[1].X = (float)1023  - OffSet;
        this.m_VertexData[1].Y = 0.0f + OffSet;
        this.m_VertexData[1].Z = 1.0f;
        this.m_VertexData[1].Tu = 1.0f;
        this.m_VertexData[1].Tv = 0.0f;
        this.m_VertexData[2].X = 0.0f - OffSet;
        this.m_VertexData[2].Y = (float)767  + OffSet;
        this.m_VertexData[2].Z = 1.0f;
        this.m_VertexData[2].Tu = 0.0f;
        this.m_VertexData[2].Tv = 1.0f;
        this.m_VertexData[3].X = (float)1023 - OffSet;
        this.m_VertexData[3].Y = (float)767 + OffSet;
        this.m_VertexData[3].Z = 1.0f;
        this.m_VertexData[3].Tu = 1.0f;
        this.m_VertexData[3].Tv = 1.0f;

        // other code snipped
}

ed: note that the offset subtraction from x and addition to y can also be re-written and subtraction from both x & y, or addition to both x & y with the same effect.
 
darkblu said:
try this

Code:
public bool Render()
{
        // other code snipped

        this.m_VertexData[0].X = 0.0f - OffSet;
        this.m_VertexData[0].Y = 0.0f + OffSet;
        this.m_VertexData[0].Z = 1.0f;
        this.m_VertexData[0].Tu = 0.0f;
        this.m_VertexData[0].Tv = 0.0f;
        this.m_VertexData[1].X = (float)1023  - OffSet;
        this.m_VertexData[1].Y = 0.0f + OffSet;
        this.m_VertexData[1].Z = 1.0f;
        this.m_VertexData[1].Tu = 1.0f;
        this.m_VertexData[1].Tv = 0.0f;
        this.m_VertexData[2].X = 0.0f - OffSet;
        this.m_VertexData[2].Y = (float)767  + OffSet;
        this.m_VertexData[2].Z = 1.0f;
        this.m_VertexData[2].Tu = 0.0f;
        this.m_VertexData[2].Tv = 1.0f;
        this.m_VertexData[3].X = (float)1023 - OffSet;
        this.m_VertexData[3].Y = (float)767 + OffSet;
        this.m_VertexData[3].Z = 1.0f;
        this.m_VertexData[3].Tu = 1.0f;
        this.m_VertexData[3].Tv = 1.0f;

        // other code snipped
}

ed: note that the offset subtraction from x and addition to y can also be re-written and subtraction from both x & y, or addition to both x & y with the same effect.

Sorry, but that gave a bit worse result :(, it must be something I'm just overlooking, but I can't figure out what it is.
 
darkblu said:
hmm. btw, on your last shot you still have got some form of oversampling. bilinear or FSAA.

Well is there a way to force it off in the render code? because I can not find any setting in the control panel option for the intel graphics or directx.
 
Tsmit42 said:
darkblu said:
hmm. btw, on your last shot you still have got some form of oversampling. bilinear or FSAA.

Well is there a way to force it off in the render code? because I can not find any setting in the control panel option for the intel graphics or directx.

sorry, c# is not my cup of tea. look in the docs for something along the lines of D3DTSS_MAGFILTER, D3DTSS_MINFILTER, D3DTSS_MIPFILTER.
 
What format is the texture?
Do you have mipmaps on?


In the mean time looking at your code, you need to set the Mip filter to None, rather than point.
 
Ok this is the Image Class that im using.

Code:
#region Using directives

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

#endregion

namespace RTSGame
{
    public class Image : IDisposable
    {
        private Texture m_Image = null;
        private ImageInformation m_ImageInformation = new ImageInformation();
        private string m_Filename;
        private Device m_Device;

        public Image(Device _Device , string _Filename)
        {
            this.m_Device = _Device;
            this.m_Filename = _Filename;
            this.Load();
        }

        public void Load()
        {
            try
            {
                this.m_ImageInformation = new ImageInformation();
                this.m_ImageInformation = TextureLoader.ImageInformationFromFile(this.m_Filename);
                this.m_Image = TextureLoader.FromFile(this.m_Device, this.m_Filename);
            }
            catch (DirectXException Error)
            {
                Console.AddLine("Unable to load image " + this.m_Filename);
                Console.AddLine(Error.ErrorString);
            }
            catch (Exception Error)
            {
                Console.AddLine("Unable to load image " + this.m_Filename);
                Console.AddLine(Error.Message);
            }
        }

        public void Dispose()
        {
            this.m_Image.Dispose();
        }

        public Texture Texture
        {
            get{return m_Image;}
        }

        public Size Size
        {
            get { return new Size(this.m_ImageInformation.Width , this.m_ImageInformation.Height); }
        }

        public Rectangle Rectangle
        {
            get { return new Rectangle(0, 0, this.m_ImageInformation.Width, this.m_ImageInformation.Height); }
        }

    }
}

And this is my initializing method.

Code:
public virtual void Initialize()
        {
            AdapterInformation AdapterInfo = Microsoft.DirectX.Direct3D.Manager.Adapters[0];
            this.m_PresentParameters = new PresentParameters();
            this.m_PresentParameters.BackBufferCount = 1;
            this.m_PresentParameters.BackBufferFormat = AdapterInfo.CurrentDisplayMode.Format;
            this.m_PresentParameters.BackBufferHeight = AdapterInfo.CurrentDisplayMode.Height;
            this.m_PresentParameters.BackBufferWidth = AdapterInfo.CurrentDisplayMode.Width;
            this.m_PresentParameters.DeviceWindow = this;
            this.m_PresentParameters.PresentationInterval = PresentInterval.Default;
            this.m_PresentParameters.SwapEffect = SwapEffect.Discard;
            this.m_PresentParameters.Windowed = false;
            this.m_Device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, this.m_PresentParameters);
            this.m_GameInput = new GameInput(this);
        }

and this is my framemovemethod

Code:
protected override void FrameMove()
        {
            this.GetPlayerInputs();
            this.m_Device.Clear(ClearFlags.Target, Color.Black, 1.0F, 0);
            this.m_Device.BeginScene();

            switch (this.m_GameState)
            {
                case GameState.DeveloperSplashScreen:
                    {
                        if (this.ShowSplash(@"C:\Documents and Settings\User\My Documents\My Pictures\ae\back.bmp", 8, null))
                        {
                            this.m_GameState = GameState.GameSplashScreen;
                        }
                        break;
                    }
                case GameState.GameSplashScreen:
                    {
                        if (this.ShowSplash(@"C:\Documents and Settings\User\My Documents\My Pictures\ae\GameSplash.jpg", 8, null))
                        {
                            this.m_GameState = GameState.Options;
                        }
                        break;
                    }
                case GameState.Options:
                    {
                        this.DoOptions();
                        break;
                    }
            }
            this.m_Device.EndScene();
        }

and this is the showsplash method

Code:
protected bool ShowSplash(string _Filename, byte _Duration, BackgroundTask _BackgroundTask)
        {
            bool Done = false;

            if (this.m_SplashScreen == null)
            {
                this.m_SplashScreen = new SplashScreen(this.m_Device, _Filename, _Duration);

                if (_BackgroundTask != null)
                {
                    this.m_ThreadTask = new Thread(new ThreadStart(_BackgroundTask));
                    this.m_ThreadTask.Name = "GameBackgroundTask";
                    this.m_ThreadTask.Start();
                }
            }

            Done = this.m_SplashScreen.Render();
            this.m_TimeLeft = m_SplashScreen.TimeLeft;
            
            if (Done)
            {
                this.m_SplashScreen.Dispose();
                this.m_SplashScreen = null;
            }
            return Done;
        }

edit: and my final splashscreen class

Code:
#region Using directives

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

#endregion

namespace RTSGame
{
    public class SplashScreen : IDisposable
    {
        private Device m_Device;
        private Image m_Image = null;
        private DateTime m_StartTime;
        private DateTime m_EndTime = DateTime.Now;
        private VertexBuffer m_VertexBuffer;
        private bool m_Initialized = false;
        private TimeSpan m_TimeLeft;
        private CustomVertex.TransformedTextured[] m_VertexData;

        public SplashScreen(Device _Device, string _Filename, byte _Duration )
        {
            this.m_Device = _Device;
            this.m_Image = new Image(this.m_Device, _Filename);
            this.m_StartTime = DateTime.Now;
            this.m_EndTime = DateTime.Now.AddSeconds(_Duration);
            this.m_VertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedTextured), 4, this.m_Device, Usage.WriteOnly, CustomVertex.TransformedTextured.Format, Pool.Default);
        }

        public bool Render()
        {
            try
            {
                bool FogState = this.m_Device.RenderState.FogEnable;
                this.m_Device.RenderState.FogEnable = false;
                this.m_Device.SamplerState[0].MagFilter = TextureFilter.None;
                this.m_Device.SamplerState[0].MinFilter = TextureFilter.None;
                this.m_Device.SamplerState[0].MipFilter = TextureFilter.None;
                float OffSet = 0.5f;

                this.m_VertexData = new CustomVertex.TransformedTextured[4];
                this.m_VertexData[0].X = 0.0f - OffSet;
                this.m_VertexData[0].Y = 0.0f + OffSet;
                this.m_VertexData[0].Z = 1.0f;
                this.m_VertexData[0].Tu = 0.0f;
                this.m_VertexData[0].Tv = 0.0f;
                this.m_VertexData[1].X = (float)1024;
                this.m_VertexData[1].Y = 0.0f + OffSet;
                this.m_VertexData[1].Z = 1.0f;
                this.m_VertexData[1].Tu = 1.0f;
                this.m_VertexData[1].Tv = 0.0f;
                this.m_VertexData[2].X = 0.0f - OffSet;
                this.m_VertexData[2].Y = (float)768;
                this.m_VertexData[2].Z = 1.0f;
                this.m_VertexData[2].Tu = 0.0f;
                this.m_VertexData[2].Tv = 1.0f;
                this.m_VertexData[3].X = (float)1024;
                this.m_VertexData[3].Y = (float)768;
                this.m_VertexData[3].Z = 1.0f;
                this.m_VertexData[3].Tu = 1.0f;
                this.m_VertexData[3].Tv = 1.0f;

                this.m_VertexBuffer.SetData(this.m_VertexData, 0, 0);
                this.m_Device.SetStreamSource(0, this.m_VertexBuffer, 0);
                this.m_Device.VertexFormat = CustomVertex.TransformedTextured.Format;
                this.m_Device.SetTexture(0, this.m_Image.Texture);
                this.m_Device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
                this.m_Device.RenderState.FogEnable = FogState;
            }
            catch (DirectXException Error)
            {
                Console.AddLine("Unable to display splash screen.");
                Console.AddLine(Error.ErrorString);
            }
            catch (Exception Error)
            {
                Console.AddLine("Unable to display splash screen.");
                Console.AddLine(Error.Message);
            }

            DateTime CurrentTime = DateTime.Now;
            return (CurrentTime > this.m_EndTime);
        }

        public bool Initialized
        {
            get { return this.m_Initialized; }
            set { this.m_Initialized = value; }
        }

        public TimeSpan TimeLeft
        {
            get { return this.m_TimeLeft; }
            set { this.m_TimeLeft = value; }
        }

        public void Dispose()
        {
            this.m_Image.Dispose();
        }

        public void Restore()
        {
            if (this.m_Image != null)
            {
                this.m_Image.Load();
            }
        }
    }
}

That is pretty much everything related to displaying the splash screen.
 
Back
Top