Люди написал свой первый шейдер, но эта тварь выдает какую-то гнусную перерисовку.
Эффект такой — выдается форма без всякого заполнения и лишь когда я гачинаю перемещать мышой окно тогда на секунды плявляется все что я хотел и мелькает с изображения на пустое окно.
Вот код программы (извините за объем, но как сделать это иначе нинаю ) :
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);
}
}
}
}
H_D>[skipped]
SR>> device.Present();
H_D>/*Вот эту строку пожалуй надо убить...
H_D>ты же требуешь перерисовку сразу после того, как что-то нарисовал...*/
SR>> this.Invalidate();
SR>> }
H_D>[skipped again]
SR>>
Все правильно, иначе при уменьшении размеров окна перерисовки не произойдет.
В конце концов большинство графических приложений работают постоянно, пытаясь выдать максимально возможное количество кадров в секунду.
Здравствуйте, 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>>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Здравствуйте, 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
Все это конечно хорошо.
Но вот я написал программку и она отказывается возпроизводить анимацию без связки
Еще раз повторю: Создаем метод Render, который рендерит 3D сцену[/*]
OnPaint() перекрываем и делаем там Render()[/*]
Изменяем код 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>>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Чем это принципиально отличается от вызова Invalidate() в конце OnPaint()?
Я встречал и такой и такой подходы в учебниках по Managed DirectX.
Просто интересна разница.
H_D>Еще раз повторю: H_D> H_D>Создаем метод Render, который рендерит 3D сцену[/*] H_D>OnPaint() перекрываем и делаем там Render()[/*] H_D>Изменяем код 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>
Здравствуйте, Dirichlet, Вы писали:
D>Здравствуйте, Hacker_Delphi, Вы писали:
D>Чем это принципиально отличается от вызова Invalidate() в конце OnPaint()?
D>Я встречал и такой и такой подходы в учебниках по Managed DirectX. D>Просто интересна разница.
Перерисовка происходит без участия очереди сообщений... которую можно достаточно легко загадить...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Здравствуйте, Hacker_Delphi, Вы писали:
H_D>Здравствуйте, Dirichlet, Вы писали:
D>>Здравствуйте, Hacker_Delphi, Вы писали:
D>>Чем это принципиально отличается от вызова Invalidate() в конце OnPaint()?
D>>Я встречал и такой и такой подходы в учебниках по Managed DirectX. D>>Просто интересна разница. H_D>Перерисовка происходит без участия очереди сообщений... которую можно достаточно легко загадить...
Как? В очереди может скопиться слишком много сообщений WM_PAINT?
Здравствуйте, Dirichlet, Вы писали:
D>Как? В очереди может скопиться слишком много сообщений WM_PAINT?
не, все WM_PAINT, если я правильно помню, превратятся в один... по-моему — в самый последний...
в очереди может скопиться слишком много других сообщений и до WM_PAINT дело будет идти очень долго...
DoEvents() вроде бы не доразгребает очередь до конца, так что шансов больше
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))