DX_Triangle/DX Triangle.mq5

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("Ошибка, не удалось удалить графический объект");
}
}
//+------------------------------------------------------------------+