//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+