331 lines
20 KiB
MQL5
331 lines
20 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void OnStart()
|
|
{
|
|
float4 vertex[3] = {{-0.5f, -0.5f, 0.0f, 1.0f}, {0.0f, 0.5f, 0.0f, 1.0f}, {0.5f, -0.5f, 0.0f, 1.0f}};
|
|
DXTutorial dx;
|
|
if(!dx.Init(vertex)) return;
|
|
ChartRedraw();
|
|
Sleep(1000);
|
|
if(!dx.Draw()) return;
|
|
ChartRedraw();
|
|
Sleep(1000);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
string shader = "float4 VShader( float4 Pos : POSITION ) : SV_POSITION \r\n"
|
|
" { \r\n"
|
|
" return Pos; \r\n"
|
|
" } \r\n"
|
|
" \r\n"
|
|
"float4 PShader( float4 Pos : SV_POSITION ) : SV_TARGET \r\n"
|
|
" { \r\n"
|
|
" return float4( 0.0f, 1.0f, 0.0f, 1.0f ); \r\n"
|
|
" } \r\n";
|
|
|
|
struct float4
|
|
{
|
|
float x;
|
|
float y;
|
|
float z;
|
|
float w;
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
class DXTutorial
|
|
{
|
|
private:
|
|
//--- members
|
|
int m_width;
|
|
int m_height;
|
|
uint m_image[];
|
|
string m_canvas;
|
|
string m_resource;
|
|
//--- headers
|
|
int m_dx_context;
|
|
int m_dx_vertex_shader;
|
|
int m_dx_pixel_shader;
|
|
int m_dx_buffer;
|
|
//--- methods
|
|
bool InitCanvas();
|
|
bool InitDevice(float4 &vertex[]);
|
|
void Deinit();
|
|
|
|
public:
|
|
|
|
void DXTutorial() { m_dx_context = 0; m_dx_vertex_shader = 0; m_dx_pixel_shader = 0; m_dx_buffer = 0; }
|
|
void ~DXTutorial() { Deinit(); }
|
|
|
|
bool Init(float4 &vertex[], int width, int height);
|
|
bool Draw();
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool DXTutorial::Init(float4 &vertex[], int width = 500, int height = 500)
|
|
{
|
|
if(width <= 0)
|
|
{
|
|
m_width = 500;
|
|
Print("Предупреждение, ширина изменена на 500");
|
|
}
|
|
else
|
|
{
|
|
m_width = width;
|
|
}
|
|
|
|
if(height <= 0)
|
|
{
|
|
m_height = 500;
|
|
Print("Предупреждение, высота изменена на 500");
|
|
}
|
|
else
|
|
{
|
|
m_height = height;
|
|
}
|
|
|
|
if(ArraySize(vertex) != 3)
|
|
{
|
|
Print("Ошибка, нужно 3 вершины для треугольника");
|
|
return(false);
|
|
}
|
|
|
|
for(int i = 0; i < 3; i++)
|
|
{
|
|
if(vertex[i].w != 1)
|
|
{
|
|
vertex[i].w = 1.0f;
|
|
Print("Предупреждение, vertex.w изменено на 1");
|
|
}
|
|
|
|
if(vertex[i].z != 0)
|
|
{
|
|
vertex[i].z = 0.0f;
|
|
Print("Предупреждение, vertex.z изменено на 0");
|
|
}
|
|
|
|
if(fabs(vertex[i].x) > 1 || fabs(vertex[i].y) > 1)
|
|
{
|
|
Print("Ошибка, координаты вершин должны быть в диапазоне [-1;1]");
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
ResetLastError();
|
|
|
|
if(!InitCanvas())
|
|
{
|
|
return(false);
|
|
}
|
|
|
|
if(!InitDevice(vertex))
|
|
{
|
|
return(false);
|
|
}
|
|
|
|
return(true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool DXTutorial::InitCanvas()
|
|
{
|
|
m_canvas = "DXTutorialCanvas";
|
|
m_resource = "::DXTutorialResource";
|
|
int area = m_width * m_height;
|
|
|
|
if(!ObjectCreate(0, m_canvas, OBJ_BITMAP_LABEL, 0, 0, 0))
|
|
{
|
|
Print("Ошибка, не удалось создать объект для рисования");
|
|
return(false);
|
|
}
|
|
|
|
if(!ObjectSetInteger(0, m_canvas, OBJPROP_XDISTANCE, 100))
|
|
{
|
|
Print("Предупреждение, не удалось сдвинуть объект по горизонтали");
|
|
}
|
|
|
|
if(!ObjectSetInteger(0, m_canvas, OBJPROP_YDISTANCE, 100))
|
|
{
|
|
Print("Предупреждение, не удалось сдвинуть объект по вертикали");
|
|
}
|
|
|
|
if(ArrayResize(m_image, area) != area)
|
|
{
|
|
Print("Ошибка, не удалось изменить размер массива для графического ресурса");
|
|
return(false);
|
|
}
|
|
|
|
if(ArrayInitialize(m_image, ColorToARGB(clrBlack)) != area)
|
|
{
|
|
Print("Предупреждение, не удалось инициализировать массив для графического ресурса");
|
|
}
|
|
|
|
if(!ResourceCreate(m_resource, m_image, m_width, m_height, 0, 0, m_width, COLOR_FORMAT_ARGB_NORMALIZE))
|
|
{
|
|
Print("Ошибка, не удалось создать ресурс для рисования");
|
|
return(false);
|
|
}
|
|
|
|
if(!ObjectSetString(0, m_canvas, OBJPROP_BMPFILE, m_resource))
|
|
{
|
|
Print("Ошибка, не удалось привязать ресурс к объекту");
|
|
return(false);
|
|
}
|
|
|
|
return(true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool DXTutorial::InitDevice(float4 &vertex[])
|
|
{
|
|
DXVertexLayout layout[1] = {{"POSITION", 0, DX_FORMAT_R32G32B32A32_FLOAT }};
|
|
string shader_error = "";
|
|
|
|
m_dx_context = DXContextCreate(m_width, m_height);
|
|
if(m_dx_context == INVALID_HANDLE)
|
|
{
|
|
Print("Ошибка, не удалось создать графический контекст: ", GetLastError());
|
|
return(false);
|
|
}
|
|
|
|
m_dx_vertex_shader = DXShaderCreate(m_dx_context, DX_SHADER_VERTEX, shader, "VShader", shader_error);
|
|
if(m_dx_vertex_shader == INVALID_HANDLE)
|
|
{
|
|
Print("Ошибка, не удалось создать вершинный шейдер: ", GetLastError());
|
|
Print("Ошибка компиляции шейдера: ", shader_error);
|
|
return(false);
|
|
}
|
|
|
|
m_dx_pixel_shader = DXShaderCreate(m_dx_context, DX_SHADER_PIXEL, shader, "PShader", shader_error);
|
|
if(m_dx_pixel_shader == INVALID_HANDLE)
|
|
{
|
|
Print("Ошибка, не удалось создать пиксельный шейдер: ", GetLastError());
|
|
Print("Ошибка компиляции шейдера: ", shader_error);
|
|
return(false);
|
|
}
|
|
|
|
m_dx_buffer = DXBufferCreate(m_dx_context, DX_BUFFER_VERTEX, vertex);
|
|
if(m_dx_buffer == INVALID_HANDLE)
|
|
{
|
|
Print("Ошибка, не удалось создать вершинный буфер: ", GetLastError());
|
|
return(false);
|
|
}
|
|
|
|
if(!DXShaderSetLayout(m_dx_vertex_shader, layout))
|
|
{
|
|
Print("Ошибка, не удалось установить разметку вершин: ", GetLastError());
|
|
return(false);
|
|
}
|
|
|
|
if(!DXPrimiveTopologySet(m_dx_context, DX_PRIMITIVE_TOPOLOGY_TRIANGLELIST))
|
|
{
|
|
Print("Ошибка, не удалось установить тип примитивов: ", GetLastError());
|
|
return(false);
|
|
}
|
|
|
|
if(!DXShaderSet(m_dx_context, m_dx_vertex_shader))
|
|
{
|
|
Print("Ошибка, не удалось установить вершинный шейдер: ", GetLastError());
|
|
return(false);
|
|
}
|
|
|
|
if(!DXShaderSet(m_dx_context, m_dx_pixel_shader))
|
|
{
|
|
Print("Ошибка, не удалось установить пиксельный шейдер: ", GetLastError());
|
|
return(false);
|
|
}
|
|
|
|
if(!DXBufferSet(m_dx_context, m_dx_buffer))
|
|
{
|
|
Print("Ошибка, не удалось установить буфер для отрисовки: ", GetLastError());
|
|
return(false);
|
|
}
|
|
|
|
return(true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool DXTutorial::Draw()
|
|
{
|
|
DXVector dx_color{1.0f, 0.0f, 0.0f, 0.5f};
|
|
|
|
if(!DXContextClearColors(m_dx_context, dx_color))
|
|
{
|
|
Print("Ошибка, не удалось очистить буфер цвета: ", GetLastError());
|
|
return(false);
|
|
}
|
|
|
|
if(!DXContextClearDepth(m_dx_context))
|
|
{
|
|
Print("Ошибка, не удалось очистить буфер глубины: ", GetLastError());
|
|
return(false);
|
|
}
|
|
|
|
if(!DXDraw(m_dx_context))
|
|
{
|
|
Print("Ошибка, не удалось отрисовать вертексы вершинного буфера: ", GetLastError());
|
|
return(false);
|
|
}
|
|
|
|
if(!DXContextGetColors(m_dx_context, m_image))
|
|
{
|
|
Print("Ошибка, не удалось получить изображение из графического контекста: ", GetLastError());
|
|
return(false);
|
|
}
|
|
|
|
if(!ResourceCreate(m_resource, m_image, m_width, m_height, 0, 0, m_width, COLOR_FORMAT_ARGB_NORMALIZE))
|
|
{
|
|
Print("Ошибка, не удалось создать ресурс для рисования");
|
|
return(false);
|
|
}
|
|
|
|
return(true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void DXTutorial::Deinit()
|
|
{
|
|
if(m_dx_pixel_shader > 0 && !DXRelease(m_dx_pixel_shader))
|
|
{
|
|
Print("Ошибка, не удалось освободить хендл пиксельного шейдера: ", GetLastError());
|
|
}
|
|
|
|
if(m_dx_vertex_shader > 0 && !DXRelease(m_dx_vertex_shader))
|
|
{
|
|
Print("Ошибка, не удалось освободить хендл вершинного шейдера: ", GetLastError());
|
|
}
|
|
|
|
if(m_dx_buffer > 0 && !DXRelease(m_dx_buffer))
|
|
{
|
|
Print("Ошибка, не удалось освободить хендл вершинного буфера: ", GetLastError());
|
|
}
|
|
|
|
if(m_dx_context > 0 && !DXRelease(m_dx_context))
|
|
{
|
|
Print("Ошибка, не удалось освободить хендл графического контекста: ", GetLastError());
|
|
}
|
|
|
|
if(!ResourceFree(m_resource))
|
|
{
|
|
Print("Ошибка, не удалось удалить графический ресурс");
|
|
}
|
|
|
|
if(!ObjectDelete(0, m_canvas))
|
|
{
|
|
Print("Ошибка, не удалось удалить графический объект");
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|