2012-10-06 3 views
0

GDI를 사용하여 그래픽을위한 기본 프레임 워크를 만들려고 노력 중입니다. 그러나 GDI는 전혀 렌더링하지 않고 있으며, 나는 흑인 클라이언트 영역을 얻었고, 내가 뭘 잘못하고 있는지 전혀 모른다.GDI가 렌더링되지 않습니다. 무엇을 잘못하고 있습니까?

//render double buffered with GDI 
      HDC frontBuffer = GetDC(m_hMainWnd); 

      HDC backBuffer; 
      HBITMAP bitmap; 
      HBITMAP oldBitmap; 

      backBuffer = CreateCompatibleDC(frontBuffer); 
      bitmap = CreateCompatibleBitmap(frontBuffer, m_ClientWidth, m_ClientHeight); 
      oldBitmap = (HBITMAP)SelectObject(backBuffer, bitmap); 

      GDI->StartDrawing(backBuffer, m_ClientWidth, m_ClientHeight); //this basically selects pens and brushes etc 
      Render(dRenderTime); //here I render some stuff 
      GDI->StopDrawing(backBuffer); //selects old pens and brushes back 

     //blit backbuffer to frontbuffer 
      BitBlt(frontBuffer, 0, 0, m_ClientWidth, m_ClientHeight, backBuffer, 0, 0, SRCCOPY); 

      SelectObject(backBuffer, oldBitmap); 
      DeleteObject(bitmap); 
      DeleteDC(backBuffer); 

      ReleaseDC(m_hMainWnd, frontBuffer); 
     } 

내가 잘못 여기서 뭐하는 거지 :

다음 코드는 지속적으로 실행하는 게임 루프 내부에? 죄송합니다. 어리석은 실수라면 Windows 프로그래밍에 익숙하지 않습니다.

편집 : 추가 코드, 요청에 따라 :

gdi.h 

    #pragma once 

#include <Windows.h> 
#include "Macros.h" 
#include "Transform.h" 
#include "Text.h" 

#define GDI gdi::getInstance() 

class gdi 
{ 
private: 
    HPEN m_OldPen; 
    HPEN m_Pen; 
    HBRUSH m_OldBrush; 
    HBRUSH m_Brush; 
    HDC m_hdc; 

    int m_DcWidth; 
    int m_DcHeight; 

    COLORREF m_Color; 
    int m_LineWidth; 

    DBlib::float3x3 m_Transform; 

    gdi(); 

    void Transform(int& x_out, int& y_out, const DBlib::float2& p) const; 
    void Transform_NDC_To_WC(int& x_out, int& y_out, const DBlib::float2& p) const; 
    void Transfrom_WC_To_NDC(DBlib::float2& p_out, int x, int y) const; 

public: 
    ~gdi(); 

    static gdi* getInstance(); 

    void StartDrawing(HDC hdc, int dcwidth, int dcheight); 
    void StopDrawing(HDC hdc); 

    void SetColor(const DBlib::float3& col); 
    void SetLineWidth(int width); 

    void SetTransform(const DBlib::float3x3& transform); 

    void DrawText(const DBlib::float2& p1, const std::tstring& s); 
    void DrawLine(const DBlib::float2& p1, const DBlib::float2& p2); 
    void DrawPolygon(const DBlib::float2* p, int size); 
    void FillPolygon(const DBlib::float2* p, int size); 
}; 

GDI.cpp

#include "gdi.h" 

gdi* gdi::getInstance() 
{ 
    static gdi instance; 
    return &instance; 
} 

gdi::gdi() 
{ 
    m_hdc = NULL; 
    m_OldPen = NULL; 
    m_OldBrush = NULL; 
    m_LineWidth = 1; 
    m_Color = RGB(0,0,0); 
    m_DcWidth = -1; 
    m_DcHeight = -1; 
    m_Transform.set_identity(); 

    m_Pen = CreatePen(PS_SOLID,1,RGB(0,0,0)); 
    m_Brush = CreateSolidBrush(RGB(255,255,255)); 
} 

gdi::~gdi() 
{ 
    if(m_Pen) DeleteObject(m_Pen); 
    if(m_Brush) DeleteObject(m_Brush); 
} 

void gdi::StartDrawing(HDC hdc, int dcwidth, int dcheight) 
{ 
    m_hdc = hdc; 
    m_DcWidth = dcwidth; 
    m_DcHeight = dcheight; 
    m_OldPen = (HPEN)SelectObject(hdc, m_Pen); 
    m_OldBrush = (HBRUSH)SelectObject(hdc, m_Brush); 
} 

void gdi::StopDrawing(HDC hdc) 
{ 
    SelectObject(hdc, m_OldPen); 
    SelectObject(hdc, m_OldBrush); 

    m_hdc = NULL; 
    m_DcWidth = -1; 
    m_DcHeight = -1; 
    m_OldPen = NULL; 
    m_OldBrush = NULL; 
} 

void gdi::SetColor(const DBlib::float3& col) 
{ 
    int r = static_cast<int>(DBlib::clamp(col.x*255.0f, 0.0f, 255.0f)); 
    int g = static_cast<int>(DBlib::clamp(col.y*255.0f, 0.0f, 255.0f)); 
    int b = static_cast<int>(DBlib::clamp(col.z*255.0f, 0.0f, 255.0f)); 
    m_Color = RGB(r,g,b); 

    SetTextColor(m_hdc, m_Color); 

    if(m_Pen) DeleteObject(m_Pen); 
    if(m_Brush) DeleteObject(m_Brush); 
    m_Pen= CreatePen(PS_SOLID, m_LineWidth, m_Color); 
    m_Brush= CreateSolidBrush(m_Color); 
} 

void gdi::SetLineWidth(int width) 
{ 
    m_LineWidth = width; 

    if(m_Pen) DeleteObject(m_Pen); 
    m_Pen= CreatePen(PS_SOLID, m_LineWidth, m_Color); 
} 

void gdi::SetTransform(const DBlib::float3x3& transform) 
{ 
    m_Transform = transform; 
} 

void gdi::Transform_NDC_To_WC(int& x_out, int& y_out, const DBlib::float2& p) const 
{ 
    x_out = static_cast<int>((p.x+1.0f)*(static_cast<float>(m_DcWidth)/2.0f)); 
    y_out = m_DcHeight - static_cast<int>((p.y+1.0f)*(static_cast<float>(m_DcHeight)/2.0f)); 
} 

void gdi::Transfrom_WC_To_NDC(DBlib::float2& p_out, int x, int y) const 
{ 
    p_out.x = static_cast<float>(x)*2.0f/static_cast<float>(m_DcWidth) - 1.0f; 
    p_out.y = -(static_cast<float>(y)*2.0f/static_cast<float>(m_DcHeight) - 1.0f); 
} 

void gdi::Transform(int& x_out, int& y_out, const DBlib::float2& p) const 
{ 
    Transform_NDC_To_WC(x_out, y_out, p*m_Transform); 
} 

void gdi::DrawText(const DBlib::float2& pos, const std::tstring& s) 
{ 
    int x,y; 
    Transform(x,y,pos); 
    TextOut(m_hdc, x, y, s.c_str(), (int)s.size()); 
} 

void gdi::DrawLine(const DBlib::float2& p1, const DBlib::float2& p2) 
{ 
    int x1,y1,x2,y2; 
    Transform(x1,y1,p1); 
    Transform(x2,y2,p2); 

    MoveToEx(m_hdc, x1, y1, NULL); 
    LineTo(m_hdc, x2, y2); 
} 

void gdi::DrawPolygon(const DBlib::float2* p, int size) 
{ 
    int* x = new int[size]; 
    int* y = new int[size]; 

    for(int i=0; i<size; ++i) { 
     Transform(x[i],y[i],*(p+i)); 
    } 
    for(int i=0; i<size; ++i) { 
     MoveToEx(m_hdc, x[i], y[i], NULL); 
     LineTo(m_hdc, x[(i+1)%size], y[(i+1)%size]); 
    } 

    delete[] x; 
    delete[] y; 
} 

void gdi::FillPolygon(const DBlib::float2* p, int size) 
{ 
    int* x = new int[size]; 
    int* y = new int[size]; 
    POINT* pts = new POINT[size]; 

    for(int i=0; i<size; ++i) { 
     Transform(x[i],y[i],*(p+i)); 
     pts[i].x = static_cast<LONG>(x[i]); 
     pts[i].y = static_cast<LONG>(y[i]); 
    } 

    Polygon(m_hdc, pts, size); 

    delete[] x; 
    delete[] y; 
    delete[] pts; 
} 

App.cpp - 렌더링 방법 정의는

void App::Render(float dTime) 
{ 
    GDI->SetColor(DBlib::float3(1.0f,1.0f,1.0f)); 
    GDI->SetLineWidth(50); 
    GDI->DrawLine(DBlib::float2(-1.0f,-1.0f), DBlib::float2(1.0f,1.0f)); 
} 
+0

코드에서'GDI' 란 무엇입니까? 렌더링 로직을 래핑하기 위해 만든 클래스라고 가정하지만, 우리가 도와 주어야한다는 것을 보여줄 필요가 있습니다. 귀하의 코드 (빠른 눈짓 후) 괜찮아 보이지만 당신은 중요한 조각이 표시되지 않습니다. 'Render'가'GDI'의 일부가 아닌 이유는 무엇입니까? – xxbbcc

+0

또 다른 것은 - 항상 게임 루프의 전체 렌더링 로직을 가질 필요는 없습니다. 무언가가 변경되었을 때 장면을 렌더링하면 변경된 부분 만 렌더링하면됩니다. 렌더링은 매우 비쌉니다. 항상 장면을 렌더링하면 많은 게임 사이클을 소모하게됩니다. 비트 맵 위에 필요할 때 장면을 렌더링 한 다음 해당 비트 맵을 화면에 블리트합니다. – xxbbcc

+0

GDI는 DrawLine, SetColor 등과 같은 편리한 유틸리티 함수가있는 싱글 톤 클래스입니다. Render()는 기본적으로 GDI 명령을 사용하여 렌더링하는 App 클래스의 메서드입니다 물건. 최소로 유지하려고했기 때문에 코드를 추가하지 않았고 게시 한 코드에 실수가 있다고 생각했습니다. 나는 그것을 지금 추가 할 것이다. – xcrypt

답변

1

이 내가하는 데 사용하는 방법입니다 GDI 렌더링 (VB6에서 번역 된 이전 제작 코드). 이것은 WM_PAINT에 대한 응답으로 사용자 (게임 루프에서) 또는 Windows가 창의 일부를 무효화 할 때 전송됩니다.

PAINTSTRUCT stPaintStruct; 
HDC hPaintDC = BeginPaint(hWnd, &stPaintStruct); 

if (hPaintDC != HANDLE_NULL) 
{ 
    // establish clipping rect using stPaintStruct.rcPaint 

    if (!m_bRendering) 
    { 
     m_bRendering = TRUE; 

     // Render() knows the output bitmap and all the content to render 
     // and makes sure resources are allocated/discarded during 
     // rendering. 
     Render(); 

     m_bRendering = FALSE; 
    } 

    EndPaint (hWnd, &stPaintStruct); 
    return (TRUE); 
} 

당신은 InvalidateRect를 사용하여 창을 무효화하여 WM_PAINT을 트리거 :

InvalidateRect (hWnd, NULL, FALSE); 

여기 클라이언트 도면에 대한 MSDN article입니다. 이 중 일부는 천천히 내게 다시오고있다. 질문에 감사한다. :) 나는 몇 년 동안 GDI를 해본 적이 없다.

+0

고마워, 나는 이것을 시험해보고 작동하는지 확인하고 시간을 좀 주겠다. :) – xcrypt

+0

아무 문제 없어요. 저는 이것을 5-6 년 동안 보지 못한 VB6 코드에서 번역했습니다. . :) 오류 조심. – xxbbcc

+0

Nop, 그것은 나를 위해 작동하지 않습니다, 나는 게임 루프 안에 InvalidateRect()를 호출하고 WM_PAINT 내에서 오래된 코드를 사용하고 시작과 끝의 페인트를 추가했지만 여전히 같은 검은 색 화면이됩니다 ... 흠 ... – xcrypt

관련 문제