DirectX 11에서 Lighting을 구현하려면, HLSL(고수준 셰이더 언어)을 사용하여 셰이더 코드를 작성해야 한다. HLSL은 Direct3D에서 셰이더 프로그래밍을 위해 사용되는 언어로, 셰이더 코드를 작성하고 컴파일하여 GPU에서 실행할 수 있는 바이너리 코드로 변환한다.

 

목차

     

     


     

     

    Lighting

     

    Lighting을 구현하는 방법은 다양하지만, 일반적으로는 Phong 또는 Blinn-Phong Lighting 모델을 사용한다. 이 모델은 ambient, diffuse, specular lighting을 사용하여 표면의 색상을 계산한다. 각각의 조명 구성 요소는 다음과 같이 계산된다.

     


    Ambient lighting

    float4 ambientColor = float4(0.2, 0.2, 0.2, 1.0); // ambient lighting의 색상값
    float4 ambientLight = ambientColor * materialColor; //ambient lighting과 material color를 곱해서 계산

     

    Diffuse lighting

    float3 lightDirection = normalize(float3(0.0, 1.0, 0.0)); // 조명의 방향 벡터
    float4 diffuseColor = float4(1.0, 1.0, 1.0, 1.0); // diffuse lighting의 색상값
    float4 diffuseLight = saturate(dot(surfaceNormal, lightDirection)) * diffuseColor * materialColor; //surface normal(표면 법선 벡터)와 조명의 방향 벡터의 내적, diffuse lighting과 material color를 곱해서 계산

     

    Specular lighting

    float3 eyeDirection = normalize(eyePosition - surfacePosition); // 눈의 방향 벡터
    float3 reflectDirection = reflect(-lightDirection, surfaceNormal); // 조명의 반사 방향 벡터
    float4 specularColor = float4(1.0, 1.0, 1.0, 1.0); // specular lighting의 색상값
    float4 specularLight = pow(saturate(dot(reflectDirection, eyeDirection)), materialShininess) * specularColor * materialColor; // 반사 방향 벡터와 눈의 방향 벡터의 내적, shininess(광택 정도)의 제곱, specular lighting과 material color를 곱해서 계산

     

    이러한 Lighting 요소들은 조명과 재질(물체의 속성)에 따라 다양하게 계산될 수 있다. 이러한 HLSL 코드는 셰이더에서 조명과 재질을 계산하는 데 사용된다.

     

     

    Shader
      Light.fx
    Lighting.fx
    UnitTest
      Lighting
      LightingDemo.h .cpp 생성

     


     

    빛 연산

     

    Diffuse Color x Texture x NdotL(Lambert)

     

    Specular Color x Texture x (Phong)

     

     

    Light(광원에서 쏘아진 빛), Reflection(반사), Eye(시야로 가는선) 이 있을때

    • 내적 dot(Reflection, Eye)를 구한 뒤
    • power(R dot E, 상수값) 를 구한다.
      • pow(0.5, 10)이라면 0.5^10
      • 상수값이 커질수록 원(=범위)은 커지지만 값을 흐려진다.
      • 상수값이 작을수록 원(=범위)은 작아지지만 빛이 강해진다.

     


     

    윤곽선 구하기

     

    윤곽선(=외각선)을 구하는 방법

    • 눈(Eye)의 방향
    • Normal의 방향
    • 두 개를 사용하여 구할 수 있다.

    바라보는 시점의 외각 = Normal 벡터와의 내적

     

     


     

    Global.fx

     

    Global.fx

    더보기
    float3 ViewPosition()
    {
    return ViewInverse._41_42_43; //카메라 변환되었던 값을 역행렬로 카메라 원래 위치를 구함
    }

    카메라의 원본 위치를 구한다.

     


     

    Light.fx

     

    Light.fx

    더보기
    struct LightDesc
    {
    float4 Ambient;
    float4 Specular;
    float3 Direction;
    float Padding;
    float3 Position;
    };
    cbuffer CB_Light
    {
    LightDesc GlobalLight;
    };
    Texture2D DiffuseMap;
    Texture2D SpecularMap;
    Texture2D NormalMap;
    TextureCube SkyCubeMap;
    Texture2D ShadowMap;
    SamplerComparisonState ShadowSampler;
    struct MaterialDesc
    {
    float4 Ambient;
    float4 Diffuse;
    float4 Specular;
    float4 Emissive;
    };
    cbuffer CB_Material
    {
    MaterialDesc Material;
    };
    MaterialDesc MakeMaterial()
    {
    MaterialDesc output;
    output.Ambient = float4(0, 0, 0, 0);
    output.Diffuse = float4(0, 0, 0, 0);
    output.Specular = float4(0, 0, 0, 0);
    output.Emissive = float4(0, 0, 0, 0);
    return output;
    }
    float3 MaterialToColor(MaterialDesc result)
    {
    return (result.Ambient + result.Diffuse + result.Specular + result.Emissive).rgb;
    }
    void AddMaterial(inout MaterialDesc result, MaterialDesc val)
    {
    result.Ambient += val.Ambient;
    result.Diffuse += val.Diffuse;
    result.Specular += val.Specular;
    result.Emissive += val.Emissive;
    }
    void Texture(inout float4 color, Texture2D t, float2 uv, SamplerState samp)
    {
    float4 sampling = t.Sample(samp, uv);
    color = color * sampling;
    }
    void Texture(inout float4 color, Texture2D t, float2 uv)
    {
    Texture(color, t, uv, LinearSampler);
    }
    void ComputeLight(out MaterialDesc output, float3 normal, float3 wPosition)
    {
    output = MakeMaterial();
    float3 direction = -GlobalLight.Direction;
    float NdotL = dot(direction, normalize(normal));
    output.Ambient = GlobalLight.Ambient * Material.Ambient;
    float3 E = normalize(ViewPosition() - wPosition);
    [flatten]
    if(NdotL > 0.0f)
    {
    output.Diffuse = Material.Diffuse * NdotL;
    [flatten]
    if(Material.Specular.a > 0.0f)
    {
    float3 R = normalize(reflect(-direction, normal));
    float RdotE = saturate(dot(R, E));
    float specular = pow(RdotE, Material.Specular.a);
    output.Specular = Material.Specular * specular * GlobalLight.Specular;
    }
    }
    [flatten]
    if(Material.Emissive.a > 0.0f)
    {
    float NdotE = dot(E, normalize(normal));
    float emissive = smoothstep(1.0f - Material.Emissive.a, 1.0f, 1.0f - saturate(NdotE));
    output.Emissive = Material.Emissive * emissive;
    }
    }
    #define MAX_POINT_LIGHTS 256
    struct PointLight
    {
    float4 Ambient;
    float4 Diffuse;
    float4 Specular;
    float4 Emissive;
    float3 Position;
    float Range;
    float Intensity;
    float3 Padding;
    };
    cbuffer CB_PointLights
    {
    uint PointLightCount;
    float3 CB_PointLights_Padding;
    PointLight PointLights[MAX_POINT_LIGHTS];
    };
    void ComputePointLight(inout MaterialDesc output, float3 normal, float3 wPosition)
    {
    output = MakeMaterial();
    MaterialDesc result = MakeMaterial();
    for (uint i = 0; i < PointLightCount; i++) //PointLight 개수만큼 for문을 돈다.
    {
    float3 light = PointLights[i].Position - wPosition;
    float dist = length(light);
    [flatten]
    if(dist > PointLights[i].Range)
    continue;
    light /= dist; //Normalize
    result.Ambient = PointLights[i].Ambient * Material.Ambient;
    float NdotL = dot(light, normalize(normal));
    float3 E = normalize(ViewPosition() - wPosition);
    [flatten]
    if (NdotL > 0.0f)
    {
    result.Diffuse = Material.Diffuse * NdotL * PointLights[i].Diffuse;
    [flatten]
    if (Material.Specular.a > 0.0f)
    {
    float3 R = normalize(reflect(-light, normal));
    float RdotE = saturate(dot(R, E));
    float specular = pow(RdotE, Material.Specular.a);
    result.Specular = Material.Specular * specular * PointLights[i].Specular;
    }
    }
    [flatten]
    if (Material.Emissive.a > 0.0f)
    {
    float NdotE = dot(E, normalize(normal));
    float emissive = smoothstep(1.0f - Material.Emissive.a, 1.0f, 1.0f - saturate(NdotE));
    result.Emissive = Material.Emissive * emissive * PointLights[i].Emissive;
    }
    float temp = 1.0f / saturate(dist / PointLights[i].Range);
    float att = temp * temp * (1.0f / max(1.0f - PointLights[i].Intensity, 1e-8f));
    output.Ambient += result.Ambient * temp;
    output.Diffuse += result.Diffuse * att;
    output.Specular += result.Specular * att;
    output.Emissive += result.Emissive * att;
    }
    }
    #define MAX_SPOT_LIGHTS 256
    struct SpotLight
    {
    float4 Ambient;
    float4 Diffuse;
    float4 Specular;
    float4 Emissive;
    float3 Position;
    float Range;
    float3 Direction;
    float Angle;
    float Intensity;
    float3 Padding;
    };
    cbuffer CB_SpotLights
    {
    uint SpotLightCount;
    float3 CB_SpotLights_Padding;
    SpotLight SpotLights[MAX_SPOT_LIGHTS];
    };
    void ComputeSpotLight(inout MaterialDesc output, float3 normal, float3 wPosition)
    {
    output = MakeMaterial();
    MaterialDesc result = MakeMaterial();
    for (uint i = 0; i < SpotLightCount; i++)
    {
    float3 light = SpotLights[i].Position - wPosition;
    float dist = length(light);
    [flatten]
    if (dist > SpotLights[i].Range)
    continue;
    light /= dist; //Normalize
    result.Ambient = SpotLights[i].Ambient * Material.Ambient;
    float NdotL = dot(light, normalize(normal));
    float3 E = normalize(ViewPosition() - wPosition);
    [flatten]
    if (NdotL > 0.0f)
    {
    result.Diffuse = Material.Diffuse * NdotL * SpotLights[i].Diffuse;
    [flatten]
    if (Material.Specular.a > 0.0f)
    {
    float3 R = normalize(reflect(-light, normal));
    float RdotE = saturate(dot(R, E));
    float specular = pow(RdotE, Material.Specular.a);
    result.Specular = Material.Specular * specular * SpotLights[i].Specular;
    }
    }
    [flatten]
    if (Material.Emissive.a > 0.0f)
    {
    float NdotE = dot(E, normalize(normal));
    float emissive = smoothstep(1.0f - Material.Emissive.a, 1.0f, 1.0f - saturate(NdotE));
    result.Emissive = Material.Emissive * emissive * SpotLights[i].Emissive;
    }
    float temp = pow(saturate(dot(-light, SpotLights[i].Direction)), SpotLights[i].Angle);
    float att = temp * (1.0f / max(1.0f - SpotLights[i].Intensity, 1e-8f));
    output.Ambient += result.Ambient * temp;
    output.Diffuse += result.Diffuse * att;
    output.Specular += result.Specular * att;
    output.Emissive += result.Emissive * att;
    }
    }
    void NormalMapping(float2 uv, float3 normal, float3 tangent, SamplerState samp)
    {
    float4 map = NormalMap.Sample(samp, uv);
    [flatten]
    if (any(map.rgb) == false)
    return;
    float3 coord = map.rgb * 2.0f - 1.0f; //-1 ~ +1
    //탄젠트 공간
    float3 N = normalize(normal); //Z
    float3 T = normalize(tangent - dot(tangent, N) * N); //X
    //float3 T = tangent;
    //float3 T = float3(1, 0, 0);
    float3 B = cross(N, T); //Y
    float3x3 TBN = float3x3(T, B, N);
    coord = mul(coord, TBN);
    Material.Diffuse *= saturate(dot(-GlobalLight.Direction, coord));
    }
    void NormalMapping(float2 uv, float3 normal, float3 tangent)
    {
    NormalMapping(uv, normal, tangent, LinearSampler);
    }
    float4 PS_AllLight(MeshOutput input)
    {
    NormalMapping(input.Uv, input.Normal, input.Tangent);
    Texture(Material.Diffuse, DiffuseMap, input.Uv);
    Texture(Material.Specular, SpecularMap, input.Uv);
    MaterialDesc output = MakeMaterial();
    MaterialDesc result = MakeMaterial();
    ComputeLight(output, input.Normal, input.wPosition);
    AddMaterial(result, output);
    ComputePointLight(output, input.Normal, input.wPosition);
    AddMaterial(result, output);
    ComputeSpotLight(output, input.Normal, input.wPosition);
    AddMaterial(result, output);
    return float4(MaterialToColor(result).rgb, 1.0f);
    }
    Texture2D ProjectorMap;
    struct ProjectorDesc
    {
    matrix View;
    matrix Projection;
    float4 Color;
    };
    cbuffer CB_Projector
    {
    ProjectorDesc Projector;
    };
    void VS_Projector(inout float4 wvp, float4 oPosition)
    {
    wvp = WorldPosition(oPosition);
    wvp = mul(wvp, Projector.View);
    wvp = mul(wvp, Projector.Projection);
    }
    void PS_Projector(inout float4 color, float4 wvp)
    {
    float3 uvw = 0;
    uvw.x = wvp.x / wvp.w * 0.5f + 0.5f;
    uvw.y = -wvp.y / wvp.w * 0.5f + 0.5f;
    uvw.z = wvp.z / wvp.w;
    [flatten]
    if (saturate(uvw.x) == uvw.x && saturate(uvw.y) == uvw.y && saturate(uvw.z) == uvw.z)
    {
    float4 map = ProjectorMap.Sample(LinearSampler, uvw.xy);
    map.rgb *= Projector.Color.rgb;
    color = lerp(color, map, map.a);
    }
    }
    cbuffer CB_Shadow
    {
    matrix ShadowView;
    matrix ShadowProjection;
    float2 ShadowMapSize;
    float ShadowBias;
    uint ShadowQuality;
    };

    ComputeLight 부분 - ComputePointLight, ComputeSpotLight도 같은 원리

    더보기
    void ComputeLight(out MaterialDesc output, float3 normal, float3 wPosition)
    {
    output = MakeMaterial();
    float3 direction = -GlobalLight.Direction;
    float NdotL = dot(direction, normalize(normal));
    output.Ambient = GlobalLight.Ambient * Material.Ambient;
    float3 E = normalize(ViewPosition() - wPosition);
    [flatten]
    if(NdotL > 0.0f)
    {
    output.Diffuse = Material.Diffuse * NdotL;
    [flatten]
    if(Material.Specular.a > 0.0f)
    {
    float3 R = normalize(reflect(-direction, normal));
    float RdotE = saturate(dot(R, E));
    float specular = pow(RdotE, Material.Specular.a);
    output.Specular = Material.Specular * specular * GlobalLight.Specular;
    }
    }
    [flatten]
    if(Material.Emissive.a > 0.0f)
    {
    float NdotE = dot(E, normalize(normal));
    float emissive = smoothstep(1.0f - Material.Emissive.a, 1.0f, 1.0f - saturate(NdotE));
    output.Emissive = Material.Emissive * emissive;
    }
    }

     

     

    Material를 Lighting.fx에 넘겨준다.

     


     

    Lighting

     

    Lighting.fx

    더보기
    #include "00_Global.fx"
    #include "00_Light.fx"
    #include "00_Render.fx"
    float4 PS(MeshOutput input) : SV_Target
    {
    Texture(Material.Diffuse, DiffuseMap, input.Uv);
    Texture(Material.Specular, SpecularMap, input.Uv);
    MaterialDesc output;
    ComputeLight(output, input.Normal, input.wPosition);
    return float4(MaterialToColor(output), 1.0f);
    }
    technique11 T0
    {
    P_VP(P0, VS_Mesh, PS)
    P_VP(P1, VS_Model, PS)
    P_VP(P2, VS_Animation, PS)
    }

     


     

    LightingDemo

     

    LightingDemo.h

    더보기
    #pragma once
    #include "Systems/IExecute.h"
    class LightingDemo : public IExecute
    {
    public:
    virtual void Initialize() override;
    virtual void Ready() override {}
    virtual void Destroy() override {}
    virtual void Update() override;
    virtual void PreRender() override {}
    virtual void Render() override;
    virtual void PostRender() override {}
    virtual void ResizeScreen() override {}
    private:
    void Mesh();
    void Airplane();
    void Kachujin();
    void KachujinCollider();
    void KachujinWeapon();
    void Pass(UINT mesh, UINT model, UINT anim);
    private:
    Shader* shader;
    CubeSky* sky;
    Material* floor;
    Material* stone;
    Material* brick;
    Material* wall;
    MeshRender* cube;
    MeshRender* cylinder;
    MeshRender* sphere;
    MeshRender* grid;
    ModelRender* airplane = NULL;
    ModelAnimator* kachujin = NULL;
    Transform* colliderInitTransforms;
    ColliderObject** colliders;
    ModelRender* weapon = NULL;
    Transform* weaponInitTransform;
    vector<MeshRender *> meshes;
    vector<ModelRender *> models;
    vector<ModelAnimator *> animators;
    };

     

     

    LightingDemo.cpp

    더보기
    #include "stdafx.h"
    #include "LightingDemo.h"
    void LightingDemo::Initialize()
    {
    Context::Get()->GetCamera()->RotationDegree(20, 0, 0);
    Context::Get()->GetCamera()->Position(1, 36, -85);
    //Performance perfomence;
    //perfomence.Start();
    //{
    shader = new Shader(L"75_Lighting.fxo");
    //}
    //float t = perfomence.End();
    //MessageBox(D3D::GetDesc().Handle, to_wstring(t).c_str(), L"", MB_OK);
    sky = new CubeSky(L"Environment/GrassCube1024.dds");
    Mesh();
    Airplane();
    Kachujin();
    KachujinCollider();
    KachujinWeapon();
    }
    void LightingDemo::Update()
    {
    ImGui::ColorEdit3("Ambient", Context::Get()->Ambient());
    ImGui::ColorEdit3("Specular", Context::Get()->Specular());
    sky->Update();
    cube->Update();
    grid->Update();
    cylinder->Update();
    sphere->Update();
    airplane->Update();
    kachujin->Update();
    Matrix worlds[MAX_MODEL_TRANSFORMS];
    for (UINT i = 0; i < kachujin->GetTransformCount(); i++)
    {
    kachujin->GetAttachTransform(i, worlds);
    //colliders[i]->Collider->GetTransform()->World(worlds[40]);
    //colliders[i]->Collider->Update();
    weapon->GetTransform(i)->World(weaponInitTransform->World() * worlds[40]);
    }
    weapon->UpdateTransforms();
    weapon->Update();
    }
    void LightingDemo::Render()
    {
    sky->Render();
    Pass(0, 1, 2);
    wall->Render();
    sphere->Render();
    brick->Render();
    cylinder->Render();
    stone->Render();
    cube->Render();
    floor->Render();
    grid->Render();
    airplane->Render();
    kachujin->Render();
    weapon->Render();
    //for (UINT i = 0; i < kachujin->GetTransformCount(); i++)
    //colliders[i]->Collider->Render();
    }
    void LightingDemo::Mesh()
    {
    //Create Material
    {
    floor = new Material(shader);
    floor->DiffuseMap("Floor.png");
    floor->Ambient(0.2f, 0.2f, 0.2f, 20);
    floor->Specular(1, 1, 1, 20);
    floor->SpecularMap("Floor_Specular.png");
    //floor->NormalMap("Floor_Normal.png");
    stone = new Material(shader);
    stone->DiffuseMap("Stones.png");
    stone->Ambient(0.2f, 0.2f, 0.2f, 20);
    stone->Specular(1, 1, 1, 20);
    stone->SpecularMap("Stones_Specular.png");
    stone->Emissive(0.15f, 0.15f, 0.15f, 0.3f);
    //stone->NormalMap("Stones_Normal.png");
    brick = new Material(shader);
    brick->DiffuseMap("Bricks.png");
    brick->Ambient(0.2f, 0.2f, 0.2f, 20);
    brick->Specular(1, 0.3f, 0.3f, 20);
    brick->SpecularMap("Bricks_Specular.png");
    brick->Emissive(0.15f, 0.15f, 0.15f, 0.3f);
    //brick->NormalMap("Bricks_Normal.png");
    wall = new Material(shader);
    wall->DiffuseMap("Wall.png");
    wall->Ambient(0.2f, 0.2f, 0.2f, 20);
    wall->Specular(1, 1, 1, 20);
    wall->SpecularMap("Wall_Specular.png");
    wall->Emissive(0.15f, 0.15f, 0.15f, 0.3f);
    //wall->NormalMap("Wall_Normal.png");
    }
    //Create Mesh
    {
    Transform* transform = NULL;
    cube = new MeshRender(shader, new MeshCube());
    transform = cube->AddTransform();
    transform->Position(0, 5, 0);
    transform->Scale(20, 10, 20);
    grid = new MeshRender(shader, new MeshGrid(5, 5));
    transform = grid->AddTransform();
    transform->Position(0, 0, 0);
    transform->Scale(12, 1, 12);
    cylinder = new MeshRender(shader, new MeshCylinder(0.5f, 3.0f, 20, 20));
    sphere = new MeshRender(shader, new MeshSphere(0.5f, 20, 20));
    for (UINT i = 0; i < 5; i++)
    {
    transform = cylinder->AddTransform();
    transform->Position(-30, 6, -15.0f + (float)i * 15.0f);
    transform->Scale(5, 5, 5);
    transform = cylinder->AddTransform();
    transform->Position(30, 6, -15.0f + (float)i * 15.0f);
    transform->Scale(5, 5, 5);
    transform = sphere->AddTransform();
    transform->Position(-30, 15.5f, -15.0f + (float)i * 15.0f);
    transform->Scale(5, 5, 5);
    transform = sphere->AddTransform();
    transform->Position(30, 15.5f, -15.0f + (float)i * 15.0f);
    transform->Scale(5, 5, 5);
    }
    }
    sphere->UpdateTransforms();
    cylinder->UpdateTransforms();
    cube->UpdateTransforms();
    grid->UpdateTransforms();
    meshes.push_back(sphere);
    meshes.push_back(cylinder);
    meshes.push_back(cube);
    meshes.push_back(grid);
    }
    void LightingDemo::Airplane()
    {
    airplane = new ModelRender(shader);
    airplane->ReadMesh(L"B787/Airplane");
    airplane->ReadMaterial(L"B787/Airplane");
    Transform* transform = airplane->AddTransform();
    transform->Position(2.0f, 9.91f, 2.0f);
    transform->Scale(0.004f, 0.004f, 0.004f);
    airplane->UpdateTransforms();
    models.push_back(airplane);
    }
    void LightingDemo::Kachujin()
    {
    kachujin = new ModelAnimator(shader);
    kachujin->ReadMesh(L"Kachujin/Mesh");
    kachujin->ReadMaterial(L"Kachujin/Mesh");
    kachujin->ReadClip(L"Kachujin/Sword And Shield Idle");
    kachujin->ReadClip(L"Kachujin/Sword And Shield Walk");
    kachujin->ReadClip(L"Kachujin/Sword And Shield Run");
    kachujin->ReadClip(L"Kachujin/Sword And Shield Slash");
    kachujin->ReadClip(L"Kachujin/Salsa Dancing");
    Transform* transform = NULL;
    transform = kachujin->AddTransform();
    transform->Position(0, 0, -30);
    transform->Scale(0.075f, 0.075f, 0.075f);
    kachujin->PlayTweenMode(0, 0, 1.0f);
    transform = kachujin->AddTransform();
    transform->Position(-15, 0, -30);
    transform->Scale(0.075f, 0.075f, 0.075f);
    kachujin->PlayTweenMode(1, 1, 1.0f);
    transform = kachujin->AddTransform();
    transform->Position(-30, 0, -30);
    transform->Scale(0.075f, 0.075f, 0.075f);
    kachujin->PlayTweenMode(2, 2, 0.75f);
    transform = kachujin->AddTransform();
    transform->Position(15, 0, -30);
    transform->Scale(0.075f, 0.075f, 0.075f);
    kachujin->PlayBlendMode(3, 0, 1, 2);
    kachujin->SetBlendAlpha(3, 1.5f);
    transform = kachujin->AddTransform();
    transform->Position(30, 0, -32.5f);
    transform->Scale(0.075f, 0.075f, 0.075f);
    kachujin->PlayTweenMode(4, 4, 0.75f);
    kachujin->UpdateTransforms();
    animators.push_back(kachujin);
    }
    void LightingDemo::KachujinCollider()
    {
    UINT count = kachujin->GetTransformCount();
    colliders = new ColliderObject*[count];
    colliderInitTransforms = new Transform();
    colliderInitTransforms->Position(-2.9f, 1.45f, -50.0f);
    colliderInitTransforms->Scale(5, 5, 75);
    for (UINT i = 0; i < count; i++)
    {
    colliders[i] = new ColliderObject();
    //colliders[i]->Init = new Transform();
    //colliders[i]->Init->Position(0, 0, 0);
    //colliders[i]->Init->Scale(10, 30, 10);
    colliders[i]->Transform = new Transform();
    //colliders[i]->Collider = new Collider(colliders[i]->Transform, colliders[i]->Init);
    colliders[i]->Collider = new Collider(colliders[i]->Transform, colliderInitTransforms);
    }
    }
    void LightingDemo::KachujinWeapon()
    {
    weapon = new ModelRender(shader);
    weapon->ReadMesh(L"Weapon/Sword");
    weapon->ReadMaterial(L"Weapon/Sword");
    UINT count = kachujin->GetTransformCount();
    for (UINT i = 0; i < count; i++)
    weapon->AddTransform();
    weapon->UpdateTransforms();
    models.push_back(weapon);
    weaponInitTransform = new Transform();
    weaponInitTransform->Position(-2.9f, 1.45f, -6.45f);
    weaponInitTransform->Scale(0.5f, 0.5f, 0.75f);
    weaponInitTransform->Rotation(0, 0, 1);
    }
    void LightingDemo::Pass(UINT mesh, UINT model, UINT anim)
    {
    for (MeshRender* temp : meshes)
    temp->Pass(mesh);
    for (ModelRender* temp : models)
    temp->Pass(model);
    for (ModelAnimator* temp : animators)
    temp->Pass(anim);
    }

     


     

    실행화면

     

    Specular를 조정한 결과

     

     

    윤곽선 효과를 적용한 결과