728x90

D3DXCompileShader() -> HLSL로 작성한 셰이더 코드를 컴파일하거나 실패에 대한 문법 에러를 검사하는 함수.

 

D3DXCompileShaderFromFile() -> 파일에서 작성한 HLSL일때 사용하는 함수.

 

D3DXDeclaratorFromFVF() -> FVF를 사용한 정점 선언값을 채워 넣는 함수.

CreateVertexDeclaration() -> 정점 선언값으로 정점들 선언 정보 (LPDIRECT3DVERTEXDECLARATION9)을 생성하는 함수.

 

FVF(Flexible Vertex Format) -> 유연한 정점 포멧, 사용할 정점의 다양한 정보들을 사용자가 필요한 부분만 골라서 정의하여 유연하게 쓸 수 있는 방법

정점에는 많은 정보를 필요로 하지만 매번 모든 정보가 필요한 것이 아니기 때문에 사용자가 사용할 용도에 따라서 원하는 정보만 포함하여 정점을 구성하므로 용량 효율이 증가. 

 

CreateVertexShader(), CreatePixelShader() -> 컴파일 한 결과를 메모리에 적재하기 위해 정점 셰이더 또는 픽셀 셰이더 객체를 생성한다.

 

SetRenderState() -> 랜더링 상태를 설정한다.

 

SetVertexShader(), SetPixelShader() -> 정점셰이더 또는 픽셀 셰이더 사용을 명시함으로써 프로그램 가능한 파이프라인 사용을 알린다. null값을 넣으면 객체 사용을 해제 하고 고정 파이프라인으로 돌아 온다.

 

SetVertexDeclaration() -> 정점들 선언 정보를 디바이스에 설정한다. null값을 넣으면 해제.

 

DrawPrimitive() -> 정점들을 이용하여 그린다.

 

D3DXMatrixIdentity() -> 단위 형랠로 초기화 해줌.

 

D3DXCreateTextureFromFile() -> 외부로 부터 이미지를 읽을때 사용, 이미지의 크기가 2의 제곱승 이여야 한다.

 

SetSamplerState() -> 기본적으로 텍스처는 스크린의 삼각형에 입혀질때, 텍스처 삼각형이 스크린 삼각형 보다 작다면 텍스처 크기를 확대하고, 크다면 텍스터 크기를 축소하여 크기를 마춘다 이 경우 왜곡이 발생할수도 있는데 이 왜곡을 줄이기위해서 이 함수를 사용하여 필터링을 한다.

(1. 첫번째 인자는 텍스쳐 스테이지.

 2. 두번째 인자는 어떤 필터인지.

 3. 세번째 인자는 필터링 방식을 지칭한다.

 

 2. 필터 종류

 D3DSAMP_MINFILTER - 확대 필터

 D3DSAMP_MAGFILTER - 축소 필터

 D3DSAMP_MIPFILTER - 밉맵 레벨간 사용하는 텍스처 필터

 

 3.필터링 방식

D3DTEXF_POINT - 근접점 샘플링, 디폴트 방식이며 품질이 가장 떨어진다, 계산이 빠르다. 텍스처와   primitive 이미지의 크기가 비슷할때 가장 효과적, 크기가 다르면 확/축소 과정으로 인해 흐림,뭉침,alliasing 등의 현상 발생.

 

D3DTEXF_LINEAR - 선형 필터링, 보통 사용하는 필터링, 비교적 높은 품질, 실행속도 빠름.

 

D3DTEXF_ANISOTROPIC - 비등방성필터링, 가장 높은 품질의 결과물이 나오지만, 실행 속도가 느리다.)

 

 

728x90
Posted by 정망스
,
728x90

A 아틀라스 (a1, a2 스프라이트) 
B 아틀라스 (b1 스프라이트)
위와 같이 아틀라스 및 스프라이트가 있을때, 

!! 하나의 Panel 안에서 a1 - b1 - a2와 같은 식으로 출력하는 것은 불가능 하다고 한다. !!

 

z값은 동일 아틀라스내에서 스프라이트 간 출력 우선순위를 결정하는데 영향을 끼치지만, 
서로 다른 아틀라스사이에서 스프라이트 간 출력 우선순위 결정에는 영향을 끼치지 못한다고 한다. 

서로 다른 아틀라스간 출력은 각 아틀라스내에서 z값이 가장 작은 것 부터 출력 된다고 한다.

(아틀라스 간에 우선 순위는 해당 아틀라스 아래 스프라이트가 갖는 가장 작은 z값이 기준이고, 동일 아틀라스 내에서는 스프라이트 우선순위는 z값)


즉, a1(positoin.z=-10) -> b1(position.z=0) -> a2(position.z=10) 이란 가정하에 보면

실제로는 a1 -> a2 -> b1 순으로 출력이 된다는 것이다.

 

a1 스프라이트가 제일 작은 z값을 가지고 있으므로 아틀라스 우선 순위는 A 아틀라스 이고 z값이 제일 작기 때문에 첫번째.

 

a2 는 A 아틀라스 소속이자,  a1 다음으로 작은 z값을 가지고 있기 때문에 두번째.

 

b1 는 그다음 우선 순위인 B 아틀라스 소속이고 z값이 제일 작기 때문에 세번째.


정리하면 그래서 b1이 두번째에 출력되게 하고 싶어도 a1,a2에 가려지거나 혹은 depth나 z값을 이리저리 조정하다보면 b1이 제일 앞에 있다거나 이상한 현상이 발생 된다는 것이다. 

 

그래서 해결책이 새로운 panel을 만드는것이다. 여러가지 경우가 잇겠지만 예를 들어보면,

1) Panel1(a1 - b1) + Panel2(a2) 
2) Panel1(a1) + Panel2(b1 - a2) 

 

이런식으로 하면 본래 의도되로 될 수 있다는 것이다.

 

폰트를 사용하는 UIlabel 같은 경우에도 다이나믹 폰트나 이런것들로 인해 기능과 관리면에선 편하지만 폰트 또한 리소스들 아틀라스와 다른 아틀라스이기 때문에 위와 같은 현상이 발생 할 수 있다는 점에서 유의 하면서 사용 해야 할 듯 하다.

 

그리고 패널을 추가하게되면 드로우콜이 늘어나는데, 그렇다고 무작정 패널을 나뉘어 분류 안하는것 보단 해주는게 좋은거 같고, 또 과하게 패널을 또 분류하면 그만큼 드로우콜이 늘어나니 적절한 선에서 패널도 추가하여 사용해야 할 것 같다.


728x90
Posted by 정망스
,
728x90

음 소켓 통신을 필요로 했기 때문에 ..

우선 node.js socket.io 를 설치 해줍니다..

 

npm install -g socket.io

 

저는 node.js를 작업할 툴로 이클립스를 사용하고 있기 때문에 이클립스가

D경로에 있습니다 .

 

그래서 그런지 간단한 서버를 작동해도 socket.io를 설치했음에도 모듈을 못찾는다는 에러가 나오더군요 (아마 설치된 경로나 이런걸 못찾고 있는듯..) 이럴때는

 

인터넷에 검색해보시면 또 많은 방법이 나오는데 저 같은 경우는

 

작업하는 폴더에서 쉬프트 + 오른쪽 클릭 하셔서 여기서 명령창 열기를 한후 npm install socket.io@0.9.6 명령어를 사용하여 작업 폴더에 모듈이 바로 설치되게 했습니다.

 

이러니 오류없이 잘 되더군요 근데 명령어 뒤에 보시면 0.9.6 버전을 설치했는데

음 무슨 이유인지는 모르겠으나 최신버전으로 하니 작동이 안되더군요 아무 반응이 없음..

그래서 다른 버전으로 했더니 잘 반응하고 작동을 했읍니다..

 

우선 유니티에서 셋팅을 해줘야 할것이 있습니다.

socket.io 플러그인을 설치해줘야 하는데

https://github.com/NetEase/UnitySocketIO 이 링크로 가시면 다운 받으실수 있습니다.

(다른 소켓 라이브러리들도 많음... 더 좋은게 있을수도)

 

귀찮으시면 바로 받으세요 ..

UnitySocketIO-master.zip

받으시면 SocketIO\Bin\Debug\ 폴더 안에 있는 모든 파일들을 유니티 프로젝트에 복사해줍니다.

 

 

그럼 셋팅은 완료됫고 이제 유니티에서 소켓을 생성하고 서버에 연결후 데이터를 받아오는거 까지 해보겠습니다.

 

 

우선 위에 SocketIOClient 네임 스페이스를 추가해주셔야 됩니다. using SocketIOClient;

 

url은 이제 서버의 ip주소 와 포트번호를 입력해주시고..  127.0.0.1은 자기 컴퓨터 주소입니다..

정말 되게 테스트만 해본거라 딱히 뭐 코드도 별로 없습니다.

 

유니티 플레이를 하게되면 소켓을 생성한후 해당 url로 소켓을 연결하고

람다식을 이용했는데.. 람다식은 그냥.. 코드 내용을 간결하게 하면서 사용할수 있는.. 익명 함수라고.. 설명하면 될듯하고... 굳이 안해도 되는데 그냥 한번 써보고 싶었음...

 

아무튼 socket.on 함수는 서버쪽에서 MsgRes 라는 이벤트가 발생하면 보내오는 데이터를 받아서 간단하게 출력하는 부분입니다.

 

test() 함수는 버튼을 누르면 반응하게 만들었고 버튼을 클릭했을시 socket.emit 함수를 발생시키는데 emit는 Msg라는 이벤트를 작동해라 라고 서버에게 넘겨주면서 동시에 데이터로 문자열을 보내고 있습니다.

 

유니티는 이정도로 셋팅을 했고.. 이제는 nodejs 서버쪽을 해보겠습니다..

 

socket.io 모듈을 불러오고.. 포트번호 999로 설정해 줍니다.

 

connection 이벤트가 발생할시 .. 즉 클라이언트에서 연결 요청이 올시 연결됫다라는 connected! 문자 출력한번 해주고요..

 

그후 연결된 소켓으로 Msg 이벤트가 요청이 오면 받은데이터를 콘솔로 출력후 emit 함수로 다시 클라이언트에게 MsgRes 이벤트를 발생시키게 함과 동시에 데이터를 보내주는 역할을 하는 서버입니다..

 

이제 node.js 를 통해서 server 를 실행시켜 주시고

 

유니티를 플레이한후 버튼을 눌러주시면..

 

유니티 콘솔창에는 제가 서버로 보냇던 데이터 문자열이 다시 저에게로 돌아와서 출력이 되었고

node.js 에선 음.. 한글 인코딩이 좀 이상하게 깨지긴 햇는데 아무튼 서버에서도 재대로 데이터를 받았고 뭐 자기 할일을 잘했다는걸 볼수 있습니다.

 

우선 연동 확인 테스트 까진 됬고 이제 좀 더 공부해보면서 본격적으로 더 해봐야 겠습니다~

 

 

 

 

 

 

728x90
Posted by 정망스
,
728x90
전 글의 심플 팩토리, 팩토리 메소드와 이번 글의 추상 팩토리를 모두 합쳐 구현한 예제 소스

AbstractFactory.cpp

 

추상 팩토리 패턴이란 공통 기능을 가지되, 약간식 다른 성격을 가지는 다양한 팩토리 인스턴스를 만든 후에 그 팩토리 인스턴스들을 사용하여 객체를 생성하는 방식이다.

팩토리 메소드 패턴은 클래스가 객체를 생성하는 패턴이라 하면, 추상 팩토리 패턴은 객체가 객체를 만드는 방식이다.

 

말이 좀 어려운대.. 소스 예제로 한번 보자.

 

class Dough
{
protected:
    char dough[256];
public:
    virtual ~Dough() {};
    inline char* getChar() { return dough; }
};

class ThinCrustDough : public Dough
{
public:
    ThinCrustDough() { strcpy_s( dough, "얇은 크러스트 " ); }
};

class ThickCrustDough : public Dough
{
public:
    ThickCrustDough() { strcpy_s( dough, "두꺼운 크러스트 " ); }
};

class Sauce
{
protected:
    char sauce[256];
public:
    virtual ~Sauce() {};
    inline char* getChar() { return sauce; }
};

class MarinaraSauce : public Sauce
{
public:
    MarinaraSauce() { strcpy_s( sauce, "마리나라 " ); }
};

class TomatoSauce : public Sauce
{
public:
    TomatoSauce() { strcpy_s( sauce, "토마토 " ); }
};

class HotSauce : public Sauce
{
public:
    HotSauce() { strcpy_s( sauce, "핫 " ); }
};

class IPizzaIngredientFactory /// ingredient : 재료
{
public:
    virtual ~IPizzaIngredientFactory() {};
    virtual Dough* createDough() = 0;
    virtual Sauce* createSauce() = 0;
};

class ChicagoPizzaIngredientFactory : public IPizzaIngredientFactory
{
public:
    Dough* createDough() override
    {
        return new ThickCrustDough();
    };
    Sauce* createSauce() override
    {
        return new MarinaraSauce();
    }
};

class NYPizzaIngredientFactory : public IPizzaIngredientFactory
{
public:
    Dough* createDough() override
    {
        return new ThinCrustDough();
    };
    Sauce* createSauce() override
    {
        return new HotSauce();
    }
};

 

 

ThinCrustDough, ThickCrustDough 클래스는 Dough를 상속 받고,

MarinaraSause, TomatoSause, HotSause 클래스는 Sause를 상속받아서 공통되게 한다.

IPizzaIngredientFactory에는 가상함수로 구성된 인터페이스 이다.

 

ChicagoPizzaIngredientFactory, NYPizzaIngredientFactory 클래스는 IPizzaIngredientFactory 인터페이스를 상속받아서 각각 createDough, createSause 메소드를 오버라이딩 하여 재정의 한다.

 

이렇게 되면 피자를 만든다는 것은 동일하지만 시카고 피자를 만들때 다뤄지는 재료들, 뉴욕 피자를 만들때 다줘지는 재료들을 조금씩 서로 달리 정의할수 있다는 것이다.

 

즉 각 팩토리마다 성격을 달리 구현 할수 있기 때문에 더 유연해 진다는 것이다.

 

*추상 팩토리 패턴은

생성하려고 하는 객체가 여러가지 형태는 비슷하지만 다른 팩토리 패턴으로 생성해야 할 경우,

객체들의 생성에 대한 구현이 아닌 인터페이스만을 노출시키고 싶을 때,

객체들 중에서 특정 객체를 선택해서 생성하고 싶을 때,

관련된 제품들이 함께 사용하도록 설계해서 이 부분에 대한 규약이 다른 외부에서 사용될 때도 지켜지게 하고 싶을 때 사용하면 유용하다.

 

728x90
Posted by 정망스
,
728x90

팩토리 메서드 패턴은 객체를 생성하기 위한 인터페이스를 정의하고 어떤 클래스의 인스턴스를 생성할 지는 서브 클래스에서 결정합니다.

 

서브 클래스에서 오버라이드 된 메서드를 통해서 객체 생성 작업을 서브클래스에 캡슐화 시킬 수 있어서 클라이언트와 서브 클래스의 코드를 분리해서 유지 보수나 코드 수정에 유용합니다.

 

 

class PizzaStore
{
public:
    PizzaStore() {}
    virtual ~PizzaStore() {}

    virtual Pizza* createPizza( int number ) = 0;

    virtual Pizza* orderPizza( int number )
    {
        Pizza* pizza;

        pizza = createPizza( number );

        pizza->prepare();
        pizza->bake();
        pizza->cut();
        pizza->box();

        return pizza;
    }
};

class ChicagoPizzaStore : public PizzaStore
{
public:
    ChicagoPizzaStore()
    {
        cout<<"시카고 피자 가계 오픈"<<endl;
    }
    ~ChicagoPizzaStore()
    {
        cout<<"시카고 피자 가계 닫음"<<endl;
    }
    Pizza* createPizza( int number ) override
    {
        Pizza* object = NULL;
        switch( number )
        {
        case 1: /// 페퍼로니 피자
            object = new ChicagoPepperoniPizza();
            break;
        case 2: /// 치킨 피자
            object = new ChickenPizza();
            break;
        default:
            return object;
        }
        return object;
    }
};

class NewYorkPizzaStore : public PizzaStore
{
public:
    NewYorkPizzaStore()
    {
        cout<<"뉴욕 피자 가계 오픈"<<endl;
    }
    ~NewYorkPizzaStore()
    {
        cout<<"뉴욕 피자 가계 닫음"<<endl;
    }
    Pizza* createPizza( int number ) override
    {
        Pizza* object = NULL;
        switch( number )
        {
        case 1: /// 페퍼로니 피자
            object = new PepperoniPizza();
            break;
        case 2: /// 치킨 피자
            object = new ChickenPizza();
            break;
        default:
            return object;
        }
        return object;
    }
};

 

 

Pizza 클래스는 전 글의 심플 팩토리 패턴에서의 클래스와 동일합니다.

PizzaStore라는 클래스를 상위 클래스로 만들고 시카고 피자를 만드는 ChicagoPizzaStore, 뉴욕 피자를 만드는 NewYorkPizzaStore라는 클래스들은 PizzaStore 클래스를 상속 받습니다.

 

createPizza 메서드는 순수 가상 함수이기 때문에 각 하위 클래스인 시카코, 뉴욕 클래스 안에서 반드시 정의를 해주어야 합니다. 이로써 하위 클래스들이 각 객체의 생성을 담당하는 팩토리가 된 것입니다.

 

앞으로는 또 다른 종류의 가계가 늘어 난다고 해도 복잡한 과정이 필요 없이 서브 클래스만 추가 하여 주면 됩니다.

 

*팩토리 메소드 패턴은 하나의 객체 안에서 수많은 다른 객체들이 동적으로 생성되거나, 어떤 클래스가 자신이 생성해야 하는 객체의 클래스를 예측할 수 없을때 사용하면 유용합니다.

728x90
Posted by 정망스
,


맨 위로
홈으로 ▲위로 ▼아래로 ♥댓글쓰기 새로고침