본문 바로가기

Cocos2d-x v3.17/고급 기능

[Cocos2d-x 고급기능]Shader 와 Material

반응형

    Shader  Material

    Shader 무엇인가?

    위키백과:

    컴퓨터 그래픽스 분야에서 셰이더(shader)는 소프트웨어 명령의 집합으로 주로 그래픽 하드웨어의 렌더링 효과를 계산하는 데 쓰인다. 셰이더는 그래픽 처리 장치(GPU)의 프로그래밍이 가능한 렌더링 파이프라인을 프로그래밍하는 데 쓰인다.

     

     전문가가 정의한다면 : 컴퓨터가 어떻게 특정한 방식으로 어떤물건을 렌더링할지 결정하는 프로그램이다.간단하게 말하면 Shader GPU상에서 어떻게 렌더링할지 결정하는 프로그램이다.



    Cocos2d-x 이것을 이용해서 노드를 렌더링한다.

     

    Cocos2d-x 사용하는 Shader 언어는 OpenGL ES Shading Language v1.0 이다.

    GLSL언어를 설명하는것은 본문건의 범위를 벗어나기 때문에  자세히 알고싶다면  가이드북  보기 바란다.

    Cocos2d-x에서 모든 렌더링 가능한 노드객체는 셰이더를 사용한다.


    Shader 설정하기

    개발자는 어떤 Cocos2d-x 객체든지 직접 작성한 셰이더를 설정할수 있습니다.


    Shader 추가하는 예시:

    C++

    sprite->setGLProgramState(programState);

    sprite3d->setGLProgramState(programState);

    GLProgramState 객체는 아래 두개의 중요한것을 포함하고 있다.

    • GLProgram근본적으로 Shader이다.정점shader 픽셀shader 포함하고 있다.
    • 상태속성근본적으로 말하자면 shader  uniform 변수이다.


    만약 당신이 uniform변수에 대해 익숙하지 않고  이것이 필요한지 알고싶다면  GLSL 가이드북 보기 바란다.


    아래와 같이 Uniform변수를 GLProgramState  쉽게 설정할수 있다


    C++

    glProgramState->setUniformFloat("u_progress"0.9);

    glProgramState->setUniformVec2("u_position", Vec2(x,y));

    glProgramState->setUniformMat4("u_transform", matrix);

    콜백함수를 uniform변수로 설정할수도 있다.아래는 람다표현식을 콜백함수로 사용한 예제이다:

    C++

    glProgramState->setUniformCallback("u_progress", [](GLProgram* glProgram, Uniform* uniform)

    {

        float random = CCRANDOM_0_1();

        glProgram->setUniformLocationWith1f(uniform->location, random);

    }

    );


    GLProgramState 객체를 수동설정할수 있지만 더욱 간단한 방법은 Material객체를 사용하는 것이다.


    재질(Material)이란 무엇인가

    게임에서 아래와 같은 구체를 그리고 싶다면

    당신이 첫번쨰로 해야할 일은 기하구조를 아래와 같이 정의하는것이다.

    그다음 벽돌 텍스처를 정의하는것이다.

    이렇게 하면 목표했던 효과를 달성할수 있다.하지만  나아가서 생각해봐야 할것은

    • 만약 구체가 카메라에서 멀어진다면 퀄리티가 떨어지는 텍스처를 사용하고 싶다면?
    • 만약 벽돌에 블러효과를 넣고 싶다면?
    • 만약 조명을 On/Off 하고 싶을 경우는?

    답은 간단한 텍스처를 사용하는것이 아니라 재질(Material) 사용하는 것이다.

    재질은 여러 텍스처를 사용할수 있고 다른 어떤 특성을 가지고 있을수 있다.

    예를들면 다중렌더링같은 경우이다.

    • 재질은 하나이상의 렌더링방법을 가질수 있다.(technique)
    • 렌더링방법마다 하나이상의 pass 가질수 있다.
    • pass마다 아래와 같은것을 가지고 있다:
      • 하나의 RenderState.
      • uniform변수를 포함한 Shader 포함하고 있다.

    아래는 Material 파일이다.


    JavaScript

    // A "Material" file can contain one or more materials

    material spaceship

    {

        // A Material contains one or more Techniques.

        // In case more than one Technique is present, the first one will be the default one

        // A "Technique" describes how the material is going to be renderer

        // Techniques could:

        //  - define the render quality of the model: high quality, low quality, etc.

        //  - lit or unlit an object

        // etc...

        technique normal

        {

            // A technique can contain one or more passes

            // A "Pass" describes the "draws" that will be needed

            //   in order to achieve the desired technique

            // The 3 properties of the Passes are shader, renderState and sampler

            pass 0

            {

                // shader: responsible for the vertex and frag shaders, and its uniforms

                shader

                {

                    vertexShader = Shaders3D/3d_position_tex.vert

                    fragmentShader = Shaders3D/3d_color_tex.frag

    // uniforms, including samplers go here

                    u_color = 0.9,0.8,0.7

                    // sampler: the id is the uniform name

                    sampler u_sampler0

                    {

                        path = Sprite3DTest/boss.png

                        mipmap = true

                        wrapS = CLAMP

                        wrapT = CLAMP

                        minFilter = NEAREST_MIPMAP_LINEAR

                        magFilter = LINEAR

                    }

                }

                // renderState: responsible for depth buffer, cullface, stencil, blending, etc.

                renderState

                {

                    cullFace = true

                    cullFaceSide = FRONT

                    depthTest = true

                }

            }

        }

    }


    재질을 Sprite3D  설정하는 방법:

    C++

    Material* material = Material::createWithFilename("Materials/3d_effects.material");

    sprite3d->setMaterial(material);

    만약 당신이 다른 렌더링방법으로 변경하고 싶다면 아래와 같이 하면 된다.

    C++

    material->setTechnique("normal");

     

    렌더링 방법(Technique)

    당신은 Sprite3D 객체마다 하나의 재질만 설정할수 있다.

    그렇다고 하나의 렌더링방식으로 고정되어 있다는 뜻은 아니다.

    재질은 여러 렌더링방식(Technique) 포함시킬수 있는 특성이 있기때문이다.

    재질이 로딩될때 모든 Technique 로딩된다.

    이런 특성이 있어서 당신은 런타임때에 빠르게 객체의 렌더링효과를 변경시킬수 있다.

     

    Material::setTechnique(const std::string& name) 메서드를 사용하여 Technique 전환을 할수있다.이런 특성은 각기 다른 조명효과로 변환을 하고플때 사용할수도 있고 렌더링할 객체가 카메라에서 멀어졌을때 퀄리티가 낮은 텍스처를 사용하고 싶을때 처리할수 있다.

     

    Pass

    하나의 Technique에는 여러개의 pass 있다.

    개중에 하나의 pass 한번의 렌더링에 대응된다.

    여러 pass 있다는것은 하나의 객체가 여러  렌더링된다는것을 의미한다.

    이것이 다중 pass 렌더링 or 다중렌더링 이라고 불린다.pass마다 아래 두개의 중요한 객체가 필요하다.

    • RenderStateGPU 상태메시지를 포함한다.(예를들면: depthTestcullFacestencilTest 등등)
    • GLProgramState사용할 Shader uniform변수들을 포함하고 있다.


    재질(Material)파일 포맷

    Cocos2d-x 재질파일은 최적화된 포맷을 사용함과 동시에 다른 오픈소스 엔진의 재질파일포맷과 유사하다(GamePlay3DOGRE3D 엔진들)


    주의해야 할점:

    • 재질 파일의 확장명은 중요하지 않다.확장자를 .material 사용하는걸 추천한다.
    • 정점 셰이더와 픽셀셰이더의 확장자도 중요하지 않으니 .vert .frag 사용하는것을 추천한다.
    • Id 재질(Material),렌더링방법(Technique),pass 선택적 속성이다.
    • Material parent_material_id 통하여 다른 재질의 값을 상속받을수 있다.



    C++

    // When the .material file contains one material

    sprite3D->setMaterial("Materials/box.material");

    // When the .material file contains multiple materials

    sprite3D->setMaterial("Materials/circle.material#wood");

    필드 정의

    material material_id : parent_material_id

     

     

    {

     

     

    renderState {}

    [0..1]

    block

    technique id {}

    [0..*]

    block

    }

     

     

    technique technique_id

     

     

    {

     

     

    renderState {}

    [0..1]

    block

    pass id {}

    [0..*]

    block

    }

     

     

    pass pass_id

     

     

    {

     

     

    renderState {}

    [0..1]

    block

    shader {}

    [0..1]

    block

    }

     

     

    renderState

     

     

    {

     

     

    blend = false

    [0..1]

    bool

    blendSrc = BLEND_ENUM

    [0..1]

    enum

    blendDst = BLEND_ENUM

    [0..1]

    enum

    cullFace = false

    [0..1]

    bool

    depthTest = false

    [0..1]

    bool

    depthWrite = false

    [0..1]

    bool

    }

     

     

      frontFace = CW | CCW

    [0..1]

    enum

      depthTest = false

    [0..1]

    bool

      depthWrite = false

    [0..1]

    bool

      depthFunc = FUNC_ENUM

    [0..1]

    enum

      stencilTest = false

    [0..1]

    bool

      stencilWrite = 4294967295

    [0..1]

    uint

      stencilFunc = FUNC_ENUM

    [0..1]

    enum

      stencilFuncRef = 0

    [0..1]

    int

      stencilFuncMask = 4294967295

    [0..1]

    uint

      stencilOpSfail = STENCIL_OPERATION_ENUM

    [0..1]

    enum

      stencilOpDpfail = STENCIL_OPERATION_ENUM

    [0..1]

    enum

      stencilOpDppass = STENCIL_OPERATION_ENUM

    [0..1]

    enum

    shadershader_id

     

     

    {

     

     

    vertexShader = res/colored.vert

    [0..1]

    file path

    fragmentShader = res/colored.frag

    [0..1]

    file path

    defines = semicolon separated list

    [0..1]

    string

    uniform_name = scalar | vector

    [0..*]

    uniform

    uniform_name AUTO_BIND_ENUM

    [0..*]

    enum

    sampler uniform_name {}

    [0..*]

    block

    }

     

     

    sampler uniform_name

     

     

    {

     

     

    path = res/wood.png | @wood

    [0..1]

    image path

    mipmap = bool

    [0..1]

    bool

    wrapS = REPEAT | CLAMP

    [0..1]

    enum

    wrapT = REPEAT | CLAMP

    [0..1]

    enum

    minFilter = TEXTURE_MIN_FILTER_ENUM

    [0..1]

    enum

    magFilter = TEXTURE_MAG_FILTER_ENUM

    [0..1]

    enum

    }

     

     

    열거형 정의

    TEXTURE_MIN_FILTER_ENUM

     

    NEAREST

    Lowest quality non-mipmapped

    LINEAR

    Better quality non-mipmapped

    NEAREST_MIPMAP_NEAREST

    Fast but low quality mipmapping

    LINEAR_MIPMAP_NEAREST

     

    NEAREST_MIPMAP_LINEAR

     

    LINEAR_MIPMAP_LINEAR

    Best quality mipmapping

    TEXTURE_MAG_FILTER_ENUM

     

    NEAREST

    Lowest quality

    LINEAR

    Better quality

    BLEND_ENUM

     

    ZERO

    ONE_MINUS_DST_ALPHA

    ONE

    CONSTANT_ALPHA

    SRC_ALPHA

    ONE_MINUS_CONSTANT_ALPHA

    ONE_MINUS_SRC_ALPHA

    SRC_ALPHA_SATURATE

    DST_ALPHA

     

    CULL_FACE_SIDE_ENUM

     

    BACK

    Cull back-facing polygons.

    FRONT

    Cull front-facing polygons.

    FRONT_AND_BACK

    Cull front and back-facing polygons.

    FUNC_ENUM

     

    NEVER

    ALWAYS

    LESS

    GREATER

    EQUAL

    NOTEQUAL

    LEQUAL

    GEQUAL

    STENCIL_OPERATION_ENUM

     

    KEEP

    REPLACE

    ZERO

    INVERT

    INCR

    DECR

    INCR_WRAP

    DECR_WRAP

    데이터 타입

    • Scalar  스칼라값을 의미한다.float,int,bool 타입을 사용할수 있다.
    • Vector 콤마로 구분된 일련의 float 타입으로 이뤄져있다.
    • 미리 정의된 uniform 변수

    아래는 Cocos2d-x 미리 정의한 uniform변수들이다.

    당신은 직접 셰이더를 작성할때 이것들을 사용할수 있다.

    • CC_PMatrix: A mat4 with the projection matrix
    • CC_MVMatrix: A mat4 with the Model View matrix
    • CC_MVPMatrix: A mat4 with the Model View Projection matrix
    • CC_NormalMatrix: A mat4 with Normal Matrix
    • CC_Time: a vec4 with the elapsed time since the game was started
    • CC_Time[0] = time / 10;
    • CC_Time[1] = time;
    • CC_Time[2] = time * 2;
    • CC_Time[3] = time * 4;
    • CC_SinTime: a vec4 with the elapsed time since the game was started:
    • CC_SinTime[0] = time / 8;
    • CC_SinTime[1] = time / 4;
    • CC_SinTime[2] = time / 2;
    • CC_SinTime[3] = sinf(time);
    • CC_CosTime: a vec4 with the elapsed time since the game was started:
    • CC_CosTime[0] = time / 8;
    • CC_CosTime[1] = time / 4;
    • CC_CosTime[2] = time / 2;
    • CC_CosTime[3] = cosf(time);
    • CC_Random01: A vec4 with four random numbers between 0.0f and 1.0f
    • CC_Texture0: A sampler2D
    • CC_Texture1: A sampler2D
    • CC_Texture2: A sampler2D
    • CC_Texture3: A sampler2D

     

    출처: <http://cocos2d-x.org/docs/cocos2d-x/zh/advanced_topics/shaders.html>

     



반응형