#ifndef IDebugDrawer_h__ #define IDebugDrawer_h__ #include "render/IRenderer.h" #include "math/LifeMath.h" #include namespace LifeGraphics { #define MAX_VERTEX_COUNT 1024 struct DebugVertex { LifeMath::float3 position; LifeMath::float3 color; const DebugVertex operator *(float val) const { DebugVertex result; result.color = this->color * val; result.position = this->position * val; return result; } const DebugVertex operator +(const DebugVertex& val) const { DebugVertex result; result.color = this->color + val.color; result.position = this->position + val.position; return result; } const DebugVertex& operator *=(float val) { this->color *= val; this->position *= val; return *this; } }; struct CB_2D_DATA { LifeMath::float4 screen_size; }; class IDebugDrawer { private: IShader* debugVS; IShader* debugPS; IShader* debugVS_2d; IShader* debugPS_2d; IInputLayout* inputLayout; IVertexBuffer* debugVB; DebugVertex geom[MAX_VERTEX_COUNT]; int vertexCount; IConstantBuffer* cb_2d; DebugVertex* buf; public: IDebugDrawer(IRenderer* _renderer) :vertexCount(0) { //Vertex shader String vs(STR( "struct VS_INPUT" \ "{" \ " float4 Position : POSITION;" \ " float3 Color : LineColor;" \ "}; " \ "struct VS_OUTPUT " \ "{" \ " float4 Position : SV_Position;" \ " float3 Color : TEXCOORD0;" \ "};" \ "cbuffer perCameraData : register(b1)" \ "{" \ " row_major matrix matView;" \ " row_major matrix matProjection;" \ " row_major matrix matInvVP;" \ " float4 camPos;" \ " float4 camDir;" \ " float4 camNearFar;" \ " float4 corners[4];" \ "};"\ "VS_OUTPUT main_VS( VS_INPUT Input )" \ "{"\ " VS_OUTPUT Output = (VS_OUTPUT)0;" \ " float4 pos = float4(Input.Position.xyz, 1.0f);" \ " Output.Color = Input.Color;" \ " Output.Position = mul(pos, matInvVP);" \ " return( Output );" \ "}" )); //Pixel shader String ps(STR( "struct PS_INPUT " \ "{" \ " float4 Position : SV_Position;" \ " float3 Color : TEXCOORD0;" \ "};" \ "float4 main_PS( PS_INPUT Input ) : SV_Target" \ "{" \ " return float4(Input.Color, 1.0f);" \ "}" )); String vs_line_2d(STR( "cbuffer RT_Size: register(b1)" \ "{float bbWidth : packoffset(c0.x);float bbHeight : packoffset(c0.y);};" \ "struct VS_INPUT {float3 Position : POSITION0;float3 Color : LineColor0;};" \ "struct VS_OUTPUT {float4 Position : SV_Position;float4 Color :TEXCOORD0;};" \ "VS_OUTPUT main_VS( VS_INPUT Input ){" \ "VS_OUTPUT Output;Output.Position = float4(Input.Position.xy, 0.0f, 1.0f);" \ "Output.Position.xy = Output.Position.xy/float2(bbWidth, -bbHeight)*2.0f + float2(-1.0f,1.0f);" \ "Output.Color = float4(Input.Color.xyz, 1.0f); return( Output );}" )); String ps_2d_line(STR( "struct PS_INPUT {" \ "float4 Position : SV_Position;" \ "float4 Color : TEXCOORD0;};" \ "float4 main_PS( PS_INPUT Input ) : SV_Target" \ "{ return Input.Color;}" )); buf = new DebugVertex[2*256]; debugVS = ResourceManager::me()->CompileUserShaderVS(vs.c_str(), vs.length()); debugPS = ResourceManager::me()->CompileUserShaderPS(ps.c_str(), ps.length()); debugVS_2d = ResourceManager::me()->CompileUserShaderVS(vs_line_2d.c_str(), vs_line_2d.length()); debugPS_2d = ResourceManager::me()->CompileUserShaderPS(ps_2d_line.c_str(), ps_2d_line.length()); IInputElement* elements = new IInputElement[2]; elements[0] = IInputElement("POSITION", 0, 0, FORMAT_R32G32B32_FLOAT, 0, 0, 0); elements[1] = IInputElement("LineColor", 0, 12, FORMAT_R32G32B32_FLOAT, 0, 0, 0); inputLayout = CG::me()->GetRenderer()->CreateInputLayout(elements, 2, debugVS); debugVB = CG::me()->GetRenderer()->CreateVertexBufferDynamic(sizeof(DebugVertex)* MAX_VERTEX_COUNT,sizeof(DebugVertex)); cb_2d = CG::me()->GetRenderer()->CreateConstantBuffer(sizeof(CB_2D_DATA)); } void DrawSpline2D(DebugVertex* points, int discr_rate) { int offset = 0; DebugVertex prev; prev = points[0]; for(int i = 1; i <= discr_rate; i++) { //DebugVertex newP; DebugVertex newP = LifeCore::CubicBezier((1.0f / (float)discr_rate) * (float)i, points[0], points[1], points[2], points[3]); buf[offset++] = prev; buf[offset++] = newP; prev = newP; } DrawLines2D(buf, discr_rate); } void DrawLines2D(DebugVertex* data, int line_count) { LifeCore::IDataStream* stm = debugVB->Map(0, LF_Discard | LF_NoOverwrite); stm->Write(data, line_count * 2 * sizeof(DebugVertex)); debugVB->Unmap(); CB_2D_DATA d; d.screen_size = LifeMath::float4(640, 480,0,0); cb_2d->Update(&d, sizeof(CB_2D_DATA)); IRenderer* r = CG::me()->GetRenderer(); r->SetVSConstantBuffer(cb_2d, 1); r->SetVertexBuffer(debugVB); r->SetInputLayout(inputLayout); r->SetPrimitiveTopology(PT_LINE_LIST); r->SetVertexShader(debugVS_2d); r->SetPixelShader(debugPS_2d); r->Draw(line_count * 2, 0); } void Render() { if(vertexCount > 1) { LifeCore::IDataStream* stm = debugVB->Map(0, LF_Discard); stm->Write(&geom[0], vertexCount * sizeof(DebugVertex)); debugVB->Unmap(); IRenderer* r = CG::me()->GetRenderer(); r->SetVertexBuffer(debugVB); r->SetInputLayout(inputLayout); r->SetPrimitiveTopology(PT_LINE_LIST); r->SetVertexShader(debugVS); r->SetPixelShader(debugPS); r->Draw(vertexCount, 0); } } void Flush() { vertexCount = 0; } /*void PushLine(const LifeMath::float3& v1, const LifeMath::float3& v2) { if(vertexCount < MAX_VERTEX_COUNT) { geom[vertexCount] = v1; vertexCount++; } if(vertexCount < MAX_VERTEX_COUNT) { geom[vertexCount] = v2; vertexCount++; } }*/ void PushLine(const DebugVertex& v1, const DebugVertex& v2) { //if(vertexCount < MAX_VERTEX_COUNT) //{ geom[vertexCount++] = v1; //} //if(vertexCount < MAX_VERTEX_COUNT) //{ geom[vertexCount++] = v2; //} } }; } #endif // IDebugDrawer_h__