Проблема с перерисовкой в шейдерах
От: SedRick  
Дата: 01.02.06 20:17
Оценка:
hi all

Люди написал свой первый шейдер, но эта тварь выдает какую-то гнусную перерисовку.
Эффект такой — выдается форма без всякого заполнения и лишь когда я гачинаю перемещать мышой окно тогда на секунды плявляется все что я хотел и мелькает с изображения на пустое окно.
Вот код программы (извините за объем, но как сделать это иначе нинаю ) :

using System;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Direct3D = Microsoft.DirectX.Direct3D;

namespace VertexShaderTriang
{
    public class Form1 : Form
    {
        #region Global vars
        private Device device = null;
        private Mesh mesh = null;
        private Effect effect = null;
        private VertexDeclaration decl = null;
        private Matrix worldMatrix, viewMatrix, projMatrix;
        private float angle = 0;
        string errors = "";
        #endregion

        #region Init

        public Form1()
        {
            this.Size = new Size(1024, 768);
            this.Text = "Vertex shader triangle";
            Directory.SetCurrentDirectory(Application.StartupPath);
        }
        public bool InitDX()
        {
            PresentParameters pp = new PresentParameters();
            pp.Windowed = true;
            pp.SwapEffect = SwapEffect.Discard;
            pp.AutoDepthStencilFormat = DepthFormat.D16;
            pp.EnableAutoDepthStencil = true;
            device = new Device(0, DeviceType.Hardware, this, CreateFlags.HardwareVertexProcessing, pp);
            effect = Effect.FromFile(device, @"..\..\simple.fx", null, ShaderFlags.None, null, out errors);
            if(errors.Length > 0)
                MessageBox.Show("ERROR !\n" + errors);
            effect.Technique = "TransformDiffuse";
            projMatrix = Matrix.PerspectiveFovLH((float)Math.PI / 4, 4 / 3, 1, 100);
            viewMatrix = Matrix.LookAtLH(
                new Vector3(0, 0, 5),
                new Vector3(),
                new Vector3(0, 1, 0));
            VertexElement[] elements = new VertexElement[]{                
                new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0),
                VertexElement.VertexDeclarationEnd
            };
            decl = new VertexDeclaration(device, elements);
            mesh = Mesh.Cylinder(device, 1.5f, 1.5f, 1.5f, 36, 36);
            return true;
        }
        #endregion
        #region Render procs

        private void UpdateWorld()
        {
            angle += 0.4f;
            if(angle >= 360)
                angle = 0;
            worldMatrix = Matrix.RotationAxis(new Vector3(angle/2, angle/4, angle/6), (float)Math.PI / 4);
            Matrix worldViewProj = worldMatrix * viewMatrix * projMatrix;
            effect.SetValue("WorldViewProj", worldViewProj);
        }
        #endregion
        #region Overrides

        protected override void OnPaint(PaintEventArgs e)
        {
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Red, 1, 0);
            UpdateWorld();
            device.BeginScene();
            device.VertexDeclaration = decl;
            int numPasses = effect.Begin(0);
            for(int i = 0; i < numPasses; i++)
            {
                effect.Pass(i);
                mesh.DrawSubset(0);
            }
            effect.End();
            device.EndScene();
            device.Present();
            this.Invalidate();
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            if((byte)e.KeyChar == (byte)Keys.Escape)
                this.Close();
        }

        #endregion

        static void Main() 
        {    
            using(Form1 frm = new Form1())
            {
                frm.Show();
                frm.InitDX();                    
                Application.Run(frm);
            }
        }
    }
}


и текст шейдера :

struct VS_OUTPUT
{
    float4 pos : POSITION;
    float4 diff : COLOR0;
};

float4x4 WorldViewProj : WORLDVIEWPROJECTION;
float3 LightDir = {0, 0, -1};

VS_OUTPUT Transform(float4 pos : POSITION, float3 normal : NORMAL)
{
    VS_OUTPUT Out = (VS_OUTPUT)0;
    float4 tranceformedNormal = mul(normal, WorldViewProj);
    Out.diff.r = 1;
    Out.diff.b = 1;
    Out.diff.ga = 1;
    Out.diff *= dot(tranceformedNormal, LightDir);
    Out.pos = mul(pos, WorldViewProj);
    
    return Out;
}

technique TransformDiffuse
{
    pass P0
    {
        CullMode = None;
        VertexShader = compile vs_1_1 Transform();
        PixelShader = NULL;
    }
}


ПАМАГИТЕ ПЛЗ !!!!!
Re: Проблема с перерисовкой в шейдерах
От: Dirichlet Россия  
Дата: 02.02.06 08:33
Оценка:
Здравствуйте, SedRick, Вы писали:

SR>hi all


Добавь в конструктор формы
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
Re: Проблема с перерисовкой в шейдерах
От: Hacker_Delphi Россия  
Дата: 02.02.06 12:52
Оценка:
Здравствуйте, SedRick, Вы писали:

SR>
[skipped]
SR>        #region Overrides

SR>        protected override void OnPaint(PaintEventArgs e)
SR>        {
SR>            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Red, 1, 0);
SR>            UpdateWorld();
SR>            device.BeginScene();
SR>            device.VertexDeclaration = decl;
SR>            int numPasses = effect.Begin(0);
SR>            for(int i = 0; i < numPasses; i++)
SR>            {
SR>                effect.Pass(i);
SR>                mesh.DrawSubset(0);
SR>            }
SR>            effect.End();
SR>            device.EndScene();
SR>            device.Present();
/*Вот эту строку пожалуй надо убить... 
ты же требуешь перерисовку сразу после того, как что-то нарисовал...*/
SR>            this.Invalidate();
SR>        }
[skipped again]
SR>


SR>ПАМАГИТЕ ПЛЗ !!!!!
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Re[2]: Проблема с перерисовкой в шейдерах
От: Dirichlet Россия  
Дата: 02.02.06 14:03
Оценка:
Здравствуйте, Hacker_Delphi, Вы писали:

SR>>
H_D>[skipped]
SR>>            device.Present();
H_D>/*Вот эту строку пожалуй надо убить... 
H_D>ты же требуешь перерисовку сразу после того, как что-то нарисовал...*/
SR>>            this.Invalidate();
SR>>        }
H_D>[skipped again]
SR>>


Все правильно, иначе при уменьшении размеров окна перерисовки не произойдет.
В конце концов большинство графических приложений работают постоянно, пытаясь выдать максимально возможное количество кадров в секунду.
Re[2]: Проблема с перерисовкой в шейдерах
От: SedRick  
Дата: 02.02.06 14:42
Оценка:
Здравствуйте, Dirichlet, Вы писали:

спасибо за помощь ))
Re[3]: Проблема с перерисовкой в шейдерах
От: Hacker_Delphi Россия  
Дата: 03.02.06 08:32
Оценка:
Здравствуйте, Dirichlet, Вы писали:

D>Здравствуйте, Hacker_Delphi, Вы писали:


SR>>>
H_D>>[skipped]
SR>>>            device.Present();
H_D>>/*Вот эту строку пожалуй надо убить... 
H_D>>ты же требуешь перерисовку сразу после того, как что-то нарисовал...*/
SR>>>            this.Invalidate();
SR>>>        }
H_D>>[skipped again]
SR>>>


D>Все правильно, иначе при уменьшении размеров окна перерисовки не произойдет.

D>В конце концов большинство графических приложений работают постоянно, пытаясь выдать максимально возможное количество кадров в секунду.

при уменьшении размеров окна и надо вызывать Invalidate()
никак ни в конце перерисовки.
если уж на то пошло — можно просто по таймеру делать Render()
но Invalidate при этом делать не надо, а в OnPaint() тоже делать Render()
Invalidate() во многих случаях посылает пару сообщений WM_ERASEBACKGROUND (или как оно там) + WM_PAINT
так вот, по первому сообщению происходит очистка содержимого, по втрому — отрисовка и вполне возможно, что ты просто не видишь отрисованых данных
поверь моему опыту — убери оттуда Invalidate() не нужен он при рисовании через DirectX
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Re[4]: Проблема с перерисовкой в шейдерах
От: SedRick  
Дата: 03.02.06 08:53
Оценка: 1 (1)
Здравствуйте, Hacker_Delphi, Вы писали:

D>>Все правильно, иначе при уменьшении размеров окна перерисовки не произойдет.

D>>В конце концов большинство графических приложений работают постоянно, пытаясь выдать максимально возможное количество кадров в секунду.

H_D>при уменьшении размеров окна и надо вызывать Invalidate()

H_D>никак ни в конце перерисовки.
H_D>если уж на то пошло — можно просто по таймеру делать Render()
H_D>но Invalidate при этом делать не надо, а в OnPaint() тоже делать Render()
H_D>Invalidate() во многих случаях посылает пару сообщений WM_ERASEBACKGROUND (или как оно там) + WM_PAINT
H_D>так вот, по первому сообщению происходит очистка содержимого, по втрому — отрисовка и вполне возможно, что ты просто не видишь отрисованых данных
H_D>поверь моему опыту — убери оттуда Invalidate() не нужен он при рисовании через DirectX

Все это конечно хорошо.
Но вот я написал программку и она отказывается возпроизводить анимацию без связки

            this.SetStyle(ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint, true);
                              ....................
            this.Invalidate();
Re[5]: Проблема с перерисовкой в шейдерах
От: Hacker_Delphi Россия  
Дата: 03.02.06 13:09
Оценка:
Здравствуйте, SedRick, Вы писали:

SR>Все это конечно хорошо.

SR>Но вот я написал программку и она отказывается возпроизводить анимацию без связки
SR>
SR>            this.SetStyle(ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint, true);
SR>                              ....................
SR>            this.Invalidate();

SR>

Еще раз повторю:
  1. Создаем метод Render, который рендерит 3D сцену[/*]
  2. OnPaint() перекрываем и делаем там Render()[/*]
  3. Изменяем код static Main(), чтобы там было так:
    MainForm form = new MainForm();
    form.Visible = true;
    
    if (!form.InitializeD3D())
        throw new Exception("Error during initialization of D3D!");
        
    while (form.Created)
    {
        try
        {
            Application.DoEvents();
            form.Render();
        catch (Direct3DError err)
        {
            //...
        }
    }

    [/*]
если ты посмотришь на примеры к старым DirectX SDK (которые еще без DXUT) — там как раз тот способ, про который я говорю использовался...
P.S. за точность названия класса Exception'а не отвечаю — под рукой SDK нету.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Re[6]: Проблема с перерисовкой в шейдерах
От: Dirichlet Россия  
Дата: 03.02.06 13:29
Оценка:
Здравствуйте, Hacker_Delphi, Вы писали:

Чем это принципиально отличается от вызова Invalidate() в конце OnPaint()?

Я встречал и такой и такой подходы в учебниках по Managed DirectX.
Просто интересна разница.

H_D>Еще раз повторю:

H_D>

    H_D>
  1. Создаем метод Render, который рендерит 3D сцену[/*]
    H_D>
  2. OnPaint() перекрываем и делаем там Render()[/*]
    H_D>
  3. Изменяем код static Main(), чтобы там было так:
    H_D>
    H_D>MainForm form = new MainForm();
    H_D>form.Visible = true;
    
    H_D>if (!form.InitializeD3D())
    H_D>    throw new Exception("Error during initialization of D3D!");
        
    H_D>while (form.Created)
    H_D>{
    H_D>    try
    H_D>    {
    H_D>        Application.DoEvents();
    H_D>        form.Render();
    H_D>    catch (Direct3DError err)
    H_D>    {
    H_D>        //...
    H_D>    }
    H_D>}
    H_D>

    H_D>[/*]
    H_D>
Re[7]: Проблема с перерисовкой в шейдерах
От: Hacker_Delphi Россия  
Дата: 03.02.06 13:55
Оценка:
Здравствуйте, Dirichlet, Вы писали:

D>Здравствуйте, Hacker_Delphi, Вы писали:


D>Чем это принципиально отличается от вызова Invalidate() в конце OnPaint()?


D>Я встречал и такой и такой подходы в учебниках по Managed DirectX.

D>Просто интересна разница.
Перерисовка происходит без участия очереди сообщений... которую можно достаточно легко загадить...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Re[8]: Проблема с перерисовкой в шейдерах
От: Dirichlet Россия  
Дата: 03.02.06 14:09
Оценка:
Здравствуйте, Hacker_Delphi, Вы писали:

H_D>Здравствуйте, Dirichlet, Вы писали:


D>>Здравствуйте, Hacker_Delphi, Вы писали:


D>>Чем это принципиально отличается от вызова Invalidate() в конце OnPaint()?


D>>Я встречал и такой и такой подходы в учебниках по Managed DirectX.

D>>Просто интересна разница.
H_D>Перерисовка происходит без участия очереди сообщений... которую можно достаточно легко загадить...

Как? В очереди может скопиться слишком много сообщений WM_PAINT?
Re[9]: Проблема с перерисовкой в шейдерах
От: Hacker_Delphi Россия  
Дата: 04.02.06 06:38
Оценка:
Здравствуйте, Dirichlet, Вы писали:

D>Как? В очереди может скопиться слишком много сообщений WM_PAINT?

не, все WM_PAINT, если я правильно помню, превратятся в один... по-моему — в самый последний...
в очереди может скопиться слишком много других сообщений и до WM_PAINT дело будет идти очень долго...
DoEvents() вроде бы не доразгребает очередь до конца, так что шансов больше
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.