136 строки
5,4 КиБ
MQL5
136 строки
5,4 КиБ
MQL5
//+------------------------------------------------------------------+
| |||
//| Remnant3D.mq5 |
| |||
//| Copyright 2000-2025, MetaQuotes Ltd. |
| |||
//| https://www.mql5.com |
| |||
//+------------------------------------------------------------------+
| |||
#resource "Shaders/vertex.hlsl" as string ExtShaderVS;
| |||
#resource "Shaders/pixel.hlsl" as string ExtShaderPS;
| |||
//+------------------------------------------------------------------+
| |||
//| Vertex shader input vertex type |
| |||
//+------------------------------------------------------------------+
| |||
struct VSInputVertex
| |||
{
| |||
//--- data
| |||
float position[4];
| |||
//--- data layout
| |||
static const DXVertexLayout s_layout[1];
| |||
};
| |||
const DXVertexLayout VSInputVertex::s_layout[1]=
| |||
{
| |||
{"POSITION", 0, DX_FORMAT_R32G32B32A32_FLOAT }
| |||
};
| |||
//+------------------------------------------------------------------+
| |||
//| Pixel shader input buffer type |
| |||
//+------------------------------------------------------------------+
| |||
struct PSInputBuffer
| |||
{
| |||
float resolution[2];
| |||
float time;
| |||
float dummy;
| |||
};
| |||
//+------------------------------------------------------------------+
| |||
//| Expert initialization function |
| |||
//+------------------------------------------------------------------+
| |||
void OnStart()
| |||
{
| |||
//--- prepare the chart
| |||
ChartSetInteger(0,CHART_SHOW,false);
| |||
ChartRedraw();
| |||
//--- get chart window size
| |||
int width=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
| |||
int height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
| |||
//---
| |||
uint image[];
| |||
string objname="Reinmant3D_"+IntegerToString(ChartID());
| |||
string resname="::Reinmant3D_"+IntegerToString(ChartID());
| |||
//--- create object and empty picture
| |||
ObjectCreate(0,objname,OBJ_BITMAP_LABEL,0,0,0);
| |||
ObjectSetInteger(0,objname,OBJPROP_XDISTANCE,0);
| |||
ObjectSetInteger(0,objname,OBJPROP_YDISTANCE,0);
| |||
//--- create resource and assign to image buffer
| |||
ArrayResize(image,width*height);
| |||
ResourceCreate(resname,image,width,height,0,0,width,COLOR_FORMAT_XRGB_NOALPHA);
| |||
ObjectSetString(0,objname,OBJPROP_BMPFILE,resname);
| |||
//--- initialize DX context
| |||
int context=DXContextCreate(width,height);
| |||
//--- prepare vertices for rectangle from [-1;-1] to [1;1] in screen space
| |||
VSInputVertex vertices[]= {{{-1,-1,0.5,1.0}},{{-1,1,0.5,1.0}},{{1,1,0.5,1.0}},{{1,-1,0.5,1.0}}};
| |||
//--- prepare indices for two triangles
| |||
uint indices[]= {0,1,2, 2,3,0};
| |||
//--- create vertex and index buffer
| |||
int buffer_v=DXBufferCreate(context,DX_BUFFER_VERTEX,vertices);
| |||
int buffer_i=DXBufferCreate(context,DX_BUFFER_INDEX, indices);
| |||
//--- create shaders from sources
| |||
string str="";
| |||
int shader_v=DXShaderCreate(context,DX_SHADER_VERTEX,ExtShaderVS,"VSMain",str);
| |||
int shader_p=DXShaderCreate(context,DX_SHADER_PIXEL, ExtShaderPS,"PSMain",str);
| |||
//--- set vertex layout for vertex shader
| |||
DXShaderSetLayout(shader_v,VSInputVertex::s_layout);
| |||
//--- create input buffer and set it to pixel shader
| |||
int inputs_p[1];
| |||
inputs_p[0]=DXInputCreate(context,sizeof(PSInputBuffer));
| |||
DXShaderInputsSet(shader_p,inputs_p);
| |||
//--- update input buffer data
| |||
PSInputBuffer frame_data;
| |||
frame_data.resolution[0]=(float)width;
| |||
frame_data.resolution[1]=(float)height;
| |||
//--- set topology, buffers and shaders
| |||
DXPrimiveTopologySet(context,DX_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
| |||
DXBufferSet(context,buffer_v);
| |||
DXBufferSet(context,buffer_i);
| |||
DXShaderSet(context,shader_v);
| |||
DXShaderSet(context,shader_p);
| |||
//--- initialize fps counter
| |||
float fps=25.0;
| |||
//--- main loop
| |||
while(!IsStopped())
| |||
{
| |||
//--- check if ESC pressed
| |||
if((TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)&0x8000)!=0)
| |||
break;
| |||
//--- get current chart window size
| |||
int w=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
| |||
int h=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
| |||
//--- update size everywhere it needed
| |||
if(w!=width || h!=height)
| |||
{
| |||
width=w;
| |||
height=h;
| |||
frame_data.resolution[0]=(float)width;
| |||
frame_data.resolution[1]=(float)height;
| |||
ArrayResize(image,width*height);
| |||
DXContextSetSize(context,width,height);
| |||
}
| |||
//--- clear depth buffer
| |||
DXContextClearDepth(context);
| |||
//--- update time in shder's input buffer
| |||
frame_data.time=GetMicrosecondCount()/1000000.0f;
| |||
DXInputSet(inputs_p[0],frame_data);
| |||
//--- draw call
| |||
DXDrawIndexed(context);
| |||
//--- get result into buffer
| |||
DXContextGetColors(context,image);
| |||
//--- calculate delta time and smoothed FPS count
| |||
float delta=GetMicrosecondCount()/1000000.0f-frame_data.time;
| |||
fps=0.95f*fps+0.05f/delta;
| |||
TextOut(StringFormat("FPS: %.0f",fps),10,10,0,image,width,height,clrWhite,COLOR_FORMAT_ARGB_NORMALIZE);
| |||
//--- update resource and redraw chart
| |||
ResourceCreate(resname,image,width,height,0,0,width,COLOR_FORMAT_XRGB_NOALPHA);
| |||
ChartRedraw();
| |||
//---
| |||
Sleep(1);
| |||
}
| |||
//--- release handles
| |||
DXRelease(inputs_p[0]);
| |||
DXRelease(shader_p);
| |||
DXRelease(shader_v);
| |||
DXRelease(buffer_v);
| |||
DXRelease(buffer_i);
| |||
DXRelease(context);
| |||
//--- release resource and object
| |||
ResourceFree(resname);
| |||
ObjectDelete(0,objname);
| |||
//--- revert chart showing mode
| |||
ChartSetInteger(0,CHART_SHOW,true);
| |||
}
| |||
//+------------------------------------------------------------------+
|