URP의 Quality 셋팅의 연관 관계입니다.

이전에 빌트인 쉐이더와 다르게 Quality 셋팅을 Render Pipleline을 통해서 셋팅되는것을 볼수 있습니다.

 

 

(개인적으로 테스트하고 세팅한 값들이라 오류가 있을 수 있습니다.)

 

HDRP Project setting은 개인적으로 굉장하다고 생각됩니다.(더 많은 옵션이 있으면 좋겠다는...)

URP에서의 Project setting는 뭐랄까 굉장히 제약이 많고 할수 있는게 별로 없다는 느낌이지만, 

HDRP Project setting 정말 많은 부분을 직접 설정할수 있다는게 굉장히 매력적입니다.

 

Project Setting을 열어 초기 셋팅을 시작합니다.

 

HDRP는 기본적으로 Linear로 설정이 되어 있지만, 처음에 확인하는 것이 좋습니다.

이게 왜 중요한가는 화면에 보이는 방식과 Shader를 계산할때 수치적으로 정확하게 하기 위함이라고 생각하고 넘어가면 될 거 같습니다.

(감마와 리니어에 대한 장단점은 대마왕님 강의를 검색하셔서 보시는것을 추천합니다.)


그다음은 Graphics인데, 이게 개인적으로는 초기에는 Quality랑 좀 헛갈리는 부분이 있었습니다.

둘다 똑같이 HDRenderPipelineAsset이라는 놈을 사용합니다.

 

그냥 두시면됩니다. 그냥 기본적인 게임 Quality셋팅이라고 할수 있습니다.

 

DefaultHDRPAsset을 임의로 설정할수 있는데, 어차피 Quality에서 설정하기 때문에 이부분은 구지 건드릴 필요는 없다고 생각됩니다.(이렇게 말하면서, 본인은 medium HDRenderPipelineAsset을 여기에 바꿔놓았고..)

Quality에서 보면 이렇게 보이는것을 알수 있습니다.

 


그다음은 HDRP Default Settings로 넘어가서 대부분 그대로 두면되는데,

중요한 부분은 Light Layer names과  Volume Components를 설정하는 것입니다.

Light Layer name은 조명 레이어 설정할때 이름 변경하는 부분입니다.(기본으로 둬도 상관없는데, 은근히 헛갈리기 때문에 이름을 바꿔서 사용합니다. 레이어 이름을 어디서 변경하나 했더니...여기있었군요...)

 

Volume Components를 확인하면, 기본적으로 뭔가 많이 있습니다.

이부분은 Scene을 구성할 때 기본적으로 설정하는 포스트프로세싱입니다.

전체적으로 어떤 분위기를 잡기 위해서 설정하는 것인데, 스테이지마다 분위기가 다르고 설정해야 할 값이 다르다면

Scene에서 직접 구성하는 것 좋기 때문에 대부분 삭제하는 것 좋습니다.

전 개인적으로 Exposure를 제외하고 다 없애고 사용합니다. 어차피 Scene에서 Exposure(노출)를 따로 조정하기 때문에 이것도 의미가 크게 있진 않지만 통일된 기본셋을 하나는 넣어 두는 것이 좋다고 생각합니다.

(그외에 Shadows 처럼 크게 변경되지 않는 것들을 넣어두면 편리합니다.)

 

그리고, LookDev Volume이라는 것이 있는데, 이건 임시로 모델링에 포스트프로세싱을 볼 수 있게 해주는 별도의 툴인데,  게임 설정과는 아무런 상관이 없는 부분이라 무시하셔도 됩니다.(이게 뭔지 한참을 찾았다는...)

 


다음 제일 중요한 퀄리티 셋팅 부분입니다.

이부분을 어떻게 설정하느냐에 따라 고사양 컴퓨터와 저사양 컴퓨터에서 돌아가게 하는것을 결정하는 곳이기 때문입니다. 말그대로 퀄리티를 설정하는 부분인데, 각각 설정을 어떻게 하느냐에 따라서 포스트프로세싱이나 그림자의 퀄리티가 결정이 됩니다. 아래는 기본 HDRP 설정입니다.

근데, Quality 아래에 HDRP가 또 있습니다.

이게 뭐냐면 Quality에 있는 Very low, Medium, Ultra를 각각 컨트롤 하는 부분입니다.

일종에 세부 설정입니다.

근데, 이게 Inspector에서도 수정할수 있는 부분입니다.(편의상 이곳에 해놓은거 같습니다.)

이 퀄리티 파일은 Project에서 우클릭하여 아래처럼 생성할수 있습니다만, 아무래도 유니티에서 제공되는 기본을 가지고 변경하는것이 뭔가 맘이 편합니다.

 

중요한 Quilty 셋팅은 다음장으로...

'Unity > HDRP' 카테고리의 다른 글

Shader variant collections  (0) 2022.09.02
HDRP에서 Emssion 사용시 주의점  (0) 2022.06.24
HDRP와 URP의 빛의 차이  (0) 2022.02.10
URP, HDRP 라이트맵(shadowmask) 설정  (0) 2022.01.18
HDRP Quality 셋팅  (0) 2021.10.08
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;

#if UNITY_EDITOR // 빌드시 제외시키는 기능이다.

public class LayerChanger : EditorWindow
{
    [MenuItem("RHY/LayerChanger", false, priority: 1)]//메뉴생성


    static void ShowWindow()
    {
        // 생성되어있는 윈도우를 가져온다. 
        LayerChanger window = (LayerChanger)EditorWindow.GetWindow(typeof(LayerChanger));

    }


    void OnGUI()
    {

        if (GUI.Button(new Rect(50, 80, 180, 40), "LayerChanger"))
        {
            SkinnedMeshRenderer [] MeshR = FindObjectsOfType(typeof(SkinnedMeshRenderer)) as SkinnedMeshRenderer[]; //SkinnedMeshRenderer를 찾는다.

            List<GameObject> listGO = new List<GameObject>(); // 하나씩 찾는다.
            if (MeshR != null)
            {
                for (int i = 0; i < MeshR.Length; i++)
                    listGO.Add(MeshR[i].gameObject);
            }

            Selection.objects = listGO.ToArray(); // 선택하여준다.

            //  MeshR = GetComponentsInChildren<SkinnedMeshRenderer>();
            foreach (var meshRenderer in MeshR) //각각 물체에 레이어를 넣어준다
            {
                meshRenderer.renderingLayerMask = 1; // 첫번째 레이어 설정

                meshRenderer.renderingLayerMask |= 1 << 1; // 추가 레이어 설정
                
            }


        }
    }

}

#endif

'Unity > C#' 카테고리의 다른 글

renderingLayerMask Set  (0) 2022.06.03
물체의 랜덤 스케일  (0) 2021.01.04
캐릭터 랜덤 애니메이션  (0) 2021.01.02
재미로 만들어보는 유니티(콘솔) 로또  (0) 2020.12.29
유리가 깨지는 연출  (0) 2020.12.15

 

플랫폼 전환 사이에 일어나는 엄청난 리임포트 시간을 줄이기 위한 것으로 캐쉬된 리소스를 이용하여 리임포트 시간을 현저히 줄여준다고 합니다.

 

참고: https://lunchballer.com/archives/700

 

[Unity] 2017.4 LTS에서 2019.3으로 업그레이드시 발생한 이슈들

2017로 된 프로젝트를 2019.3에서 열었을 때, AssetDatabase Version 2로 에셋들을 리임포트 시킬지 여부를 묻는 것으로 시작한다.   AssetDatabase Version 2가 뭔가 했더니, 플랫폼 전환 사이에 일어나는 엄청

lunchballer.com

 

'Unity > ETC' 카테고리의 다른 글

Prefab에 대해서 정리해봅시다.  (0) 2022.01.18
Unity LUT  (0) 2021.10.27
UTS2 Shader 모바일용과 일반의 차이  (0) 2021.05.25
플렛폼별 대표 이미지 압축율 테스트  (0) 2021.05.13
Galaxy S21, S7, fire HD 10 스펙  (0) 2021.05.12

https://docs.google.com/document/d/1UX0319CXa29fCFAgg0qa5vnH-U6875jt0KLKUk5mke8/edit

 

URP Shader Basic

URP Shader Basic term 2 Shader란? 2 Basic simple basic code 2 Shader “shader folder name / shader name” 3 Properties에서 변수 설정하고 매터리얼에서 확인 3 SubShader 4 Shader Tag 5 Rendering Order - Queue Tag 5 Render type 5 Pass 5 HLSL

docs.google.com

https://www.youtube.com/watch?v=mlNWoROvavY 

SubShader
    {
       Tags { "RenderType" = "Opaque"
              "RenderPipeline" = "UniversalPipeline"
              "UniversalMaterialType" = "SimpleLit" 
              "IgnoreProjector" = "True"
              "ShaderModel"="4.5"}
        Pass
        {
           Name "ForwardLit"
           Tags { "LightMode" = "UniversalForward" }
           …
        }
   
        Pass
        {
            Name "ShadowCaster"
            Tags{"LightMode" = "ShadowCaster"}
          …
        }
       Pass
        {
            Name "GBuffer"
            Tags{"LightMode" = "UniversalGBuffer"}
        …
        }
       Pass
       {
            Name "DepthOnly"
            Tags{"LightMode" = "DepthOnly"}
       …
       }

아무리봐도 그다지 차이가 없는데, 풀 코드를 봐서도 그다지 두개의 차이점을 알아낼수가 없었습니다.

다만, 모바일에는 path를 주어서 path을 막아버릴수 있다는거 외에는 그래서 뭐가 정확히 다른가하고 문의한 결과.

 

Each shader in the UTS2 mobile version omits the FORWRD_DELTA pass.
This pass functionally handles the toon processing of the real-time point light, but since the real-time point light itself is a heavy function in the mobile environment, we have omitted this pass to reduce the task of shaders.

 

라고 답변이 왔습니다.

짧은 번역 능력으로 해설하자면, 모바일은 FORWRD_DELTA pass가 빠져있어서, 리얼타임 포인트라이트가 영향을 받지 않도록 설계가 되어있다고.... 

해서 다시 코드를 보니.. 빠져있군요.. 아직 갈길이 멀었군요.. 이정도는 눈치챘어야했는데.ㅋ

 

 

 

'Unity > ETC' 카테고리의 다른 글

Unity LUT  (0) 2021.10.27
Asset Database version2?  (0) 2021.05.27
플렛폼별 대표 이미지 압축율 테스트  (0) 2021.05.13
Galaxy S21, S7, fire HD 10 스펙  (0) 2021.05.12
빌드후에 라이트문제가 발생했을때  (0) 2020.12.30

글로만 봐서는 뭔가 현실감이 없어서 직접 압출율을 테스트 진행해봤습니다.

상황에 따라 다르지만, RGB Crunched ETC가 좋네요.

'Unity > ETC' 카테고리의 다른 글

Asset Database version2?  (0) 2021.05.27
UTS2 Shader 모바일용과 일반의 차이  (0) 2021.05.25
Galaxy S21, S7, fire HD 10 스펙  (0) 2021.05.12
빌드후에 라이트문제가 발생했을때  (0) 2020.12.30
Post Process 실시간 값 변경  (0) 2020.12.22

정점셰이더

struct VS_INPUT //입력을 받는 곳
{
   float4 mPosition : POSITION; //버텍스에서 위치 정보를 받기 위한 시맨틱(DirectX의 버텍스
   로부터 위치 정보를 구하는 기능)
   
   float3 mNormal : NORMAL; // 법선(노멀) 시맨틱
   
};

struct VS_OUTPUT // 정점셰이더가 위치변환 결과를 래스터라이저 하는 과정(이다음에 픽셀
//셰이더로 넘어간다.) 출력하는곳이다.

{
   float4 mPosition : POSITION; //정점 좌표를 위한 시맨틱
   float2 mUV : TEXCOORD0; // (TEXCOORD0) UV좌표 위한 시맨틱
   float2 mDiffuse : TEXCOORD1; 
   float3 mViewDir: TEXCOORD2; // 
   float3 mReflection: TEXCOORD3;  //정반사를 받기 위한 표면 시맨틱
   
};

float4x4 gWorldMatrix; // 월드 공간
float4x4 gViewMatrix;  // 뷰공간(월드공간안에 카메라로 찍힌 공간)
float4x4 gProjectionMatrix; // 투영공간(카메라에 찍힌 물체의 거리가 인지되는것을 
화면으로 그려지는 이미지?)

float4 gWorldLightPositon; //라이트 위치
float4 gWorldCameraPositon; // 카메라 위치(정반사를 구하기위함)


VS_OUTPUT vs_main( VS_INPUT Input ) // VS_OUTPUT로 보내기전에 함수를 작성하는 곳
{
   VS_OUTPUT Output; //반환할 구조체 선언

   Output.mPosition = mul( Input.mPosition, gWorldMatrix ); //mPosition을 공간으로 변환
   
   float3 lightDir = Output.mPosition.xyz - gWorldLightPositon.xyz; //노멀의 위치값을 구한다.
   //정점위치에서 빛위치을 빼주면 정점이 빛에서 어떤 위치에 있는지 알수 있다.
   //난반사를 구하는 값이다.
   lightDir = normalize(lightDir); // 벡터(vector)를 1로 만드는 과정.
   
   float3 viewDir = normalize(Output.mPosition.xyz - gWorldCameraPositon.xyz);
   //정점에서 카메라위치를 빼주면 마찬가지로 정점이 카메라에서 어떤 위치인지 알수 있다.
   //정반사를 구하는 값이다.
   Output.mViewDir = viewDir;
   
   
   Output.mPosition = mul( Output.mPosition, gViewMatrix ); //mPosition을 뷰공간화
   Output.mPosition = mul( Output.mPosition, gProjectionMatrix ); //mPosition을 투영공간화
   
   float3 worldNormal = mul(Input.mNormal, (float3x3)gWorldMatrix); //법선(노멀)을 월드공간으로 변환
   worldNormal = normalize(worldNormal); //난반사
   
   Output.mDiffuse = dot(-lightDir, worldNormal); // 법선을 구할 내적(코사인을 간략한것)
   Output.mReflection = reflect(lightDir, worldNormal); //정반사
   
   Output.mUV = Input.mUV; //텍스쳐UV

    
   return Output;
   
}

픽셀셰이더

struct PS_INPUT //화면에 출력될 픽셀정보에 필요로 하는 것을 넣는다.
//버텍스의 정보가 변화되는 내용이 없기 때문이다. mPosition만 없다.
{
   float2 mUV : TEXCOORD0;
   float3 mDiffuse : TEXCOORD1;
   float3 mViewDir: TEXCOORD2;
   float3 mReflection: TEXCOORD3;
   
};
   

float4 ps_main(PS_INPUT Input) : COLOR //ps_main함수
{   
   
   float4 albedo = tex2D(DiffuseSampler, Input.mUV); //텍스쳐
   
   //float3 diffuse = saturate(Input.mDiffuse); //난반사
    float3 diffuse = gLightColor * albedo.rgb * saturate(Input.mDiffuse);//난반사에 텍스쳐를 추가
    
   float3 reflection = normalize(Input.mReflection);
   float3 ViewDir = normalize(Input.mViewDir);
   
   float3 specular = 0;   
   if(diffuse.x >0) //정반사 (빛이 닿지않는 부분은 필요없기때문에 0이상으로 설정)
   {
      specular = saturate(dot(reflection, -ViewDir)); 
      specular = pow(specular, 20.0f); // 난반사보다 강해야 하므로,
      //빛을 강하게 받아야하니 강제로 값을 올려준다.
   
   }
   
   float3 ambient = float3(0.1f, 0.1f, 0.1f); //물체의 어두운부분이 너무 어둡지 않게
   //임의로 밝게 처리(환경광효과처럼 넣는다.) 
   //즉, 실제 반사가 되서 밝아진것이 아니라 강제로 밝게 한것이다.

   
   
   return float4(ambient + diffuse + specular, 1);
   
}

 

 

 

참고서적: 셰이더 프로그래밍입문의 RenderMonkey기반

'Unity > Code base Shader' 카테고리의 다른 글

Fake Shine  (0) 2021.02.13
Microsoft HLSL  (0) 2021.02.09
인위적 유리 셰이더  (0) 2021.02.09
Z-Buffer, Render Queue, Tag, Blending  (0) 2021.01.01
Unity Shader에 대한 이해  (0) 2021.01.01

3dsmax normal은 DirectX 기반이고,

Unity는 OpenGL방식이니깐 넣을때 헛갈리지 않는게 좋겠습니다.

 

DirectX와 같은 방향으로 맥스,크라이,소스,언리얼

 

OpenGL과 같은 방향으로 마야,블렌더,툴백,모도,유니티

회사마다 TA 역할이 다르다 보니 제가 하는 일이 무엇인가 하는 걸 좀 정리해 보았습니다.

제는 가장 많이 하는 일은 최적화 관련 일입니다.
거의 주된 업무라고 할수 있습니다. 새로운 오브젝트가 들어갈 때마다 최적화를 기본적으로 다룹니다.

캐릭터 초반설계시에는 셰이더도 만들어야 하고 본 세팅도 봐야 하고 여러 가지 시간이 좀 들지만 이후는 관리 작업이 주로입니다.
정기적으로는 새로운 배경이나, 캐릭터가 추가되었을 때마다 머터리얼 설정을 하고 필요에 따른 각종 설정을 추가하는 일입니다.
현재 제작되고 있는 캐릭터의 경우 아웃게임과 인게임의 머터리얼을 다르기 때문에 이를 분리하고 인게임의 경우 레이어로 라이트를 관리가 필요하여 이를 작업합니다. 복잡한 구조는 세팅에 대한 실수가 잦아 이를 방지하기 위해서 툴을 만들어서 관리를 하곤 합니다. 요즘에는 ChatGPT 덕분에 코딩이 익숙지 않은 저에겐 관리툴을 만들기가 훨씬 용의 해졌습니다.

 

애니메이터가 원하는 동작을 볼 수 있도록 간단한 툴을 만들기도 합니다.
이번 프로젝트는 다이나믹본을 사용하였는데(다이나믹본을 사용하자고 제시하는 일도 합니다.), 이를 확인하는 것은 유니티 내부에서만 가능했기에 이를 확인할 수 있는 간단한 Scene을 만들어서 새로운 모션을 넣어서 확인하는 기능과 다이나믹본이 문제가 없는지 확인하는 기능, 라이트를 받았을 때 캐릭터에게 어떻게 반영되는지 보여주는 등의 간단한 툴을 제작하기도 하였습니다.

가끔 기획적으로 추가되는 효과나 좋은 아이디어가 떠오르면 AD와 상의하여 추가적인 설정을 합니다.
얼마 전에는 캐릭터가 너무 창백해 보인다는 생각이 들어서 몇 번의 테스트를 거쳐서 sss 설정을 추가하였군요.

현재 저의 회사 특성상 캐릭터에 비해 배경에 많은 시간이 들곤 합니다. 배경 제작은 주로 외주라 최적화가 안된 경우가 많습니다. 아무래도 외부에서 제작되다 보니 알 수 없는 포퍼먼스 저하가 있곤 합니다. 하여 이를 필요에 따라 모델링을 다시 고치는 경우도 있고 머터리얼 설정을 다시 하곤 합니다. LOD가 필요한 경우 직접 제작하거나 외주에 맡깁니다. 가장 기억에 남았던 이슈는 알 수 없는 포퍼먼스 저하였는데 2주 정도 소비를 했던 거 같습니다. 원인은 아주 단순했는데  외주에서 카메라에 실수로 MSAA(안티엘리어싱)을 넣어 놨던 거였습니다. (그 이전에 프로그램팀에서 다른 원인을 발생시켜서 더 혼란을 주긴 했었습니다.ㅠㅠ)
아까운 2주가 소요되었지만 이게 TA 업무에서 가장 중요한 일중에 하나라고 생각합니다. 배경은 꾸준한 최적화가 필요해서 2주에서 한 달 정도 시간이 들기도 합니다. 그래서 가장 화면에 많이 띄워져 있는 것이 유니티에서 게임 배경인 경우가 많습니다.

다른 작업자들이 보기엔 저 사람을 도대체 무얼 하고 있는가 라는 의문이 들 수 있을 거라는 생각도 듭니다. 매번 같은 화면에서 무언가 계속 하지만 결과가 빠르게 나오지 않기 때문이겠지요.

제가 하는 TA로서의 업무는 AD와 PD의 신뢰를 기반으로 합니다. 이유는 정확히 언제 끝이 날지 모르는 일들이 꽤 많기 때문이고, 우리 게임에 맞는 좋은 아트를 위해서 제시할 수 있는 연구가 필요로 하기 때문입니다. 그래서 간혹의 경우 실패를 하는 경우도 있습니다. 결과를 도출했지만, 기대에 미치지 못하여 사용하지 못하는 경우도 생깁니다.(실패할 경우에는 이를 우회하거나 다른 차선책을 머릿속에 생각하곤 합니다.)
대부분은 우리 게임 속 요구하는 내용은 이미 구현된 것들이긴 하지만, 막상 내가 구현하려면 공부가 필요할 수밖에 없습니다.

 

제가 하는 일중 또 하나의 중요하다고 생각되는 일은 AD나 PD나 프로그램이나 아티스트나 이런 것이 되는가?라는 질문에 해결책을 내놓는 것입니다.(항상 방법은 있다고 생각하는 편입니다.)
가령 PD가 캐릭터가 저사양에서는 포퍼먼스 때문에 캐릭터에만 그림자만 적용하고 싶다고 했을 때, 이를 분리할 방법을 찾고 이를 적용하는 것입니다. 혼자 해결하기도 하고 아트팀이나 프로그램팀과 공조를 하기도 합니다.
그리고, 애매한 것들(아트에서 뭘 해야 하지? 프로그램에서 뭘 해줘야 하지?)을 정리하기도 합니다.

docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics

'Unity > Code base Shader' 카테고리의 다른 글

HLSL기본 (Phong shader)  (0) 2021.04.22
Fake Shine  (0) 2021.02.13
인위적 유리 셰이더  (0) 2021.02.09
Z-Buffer, Render Queue, Tag, Blending  (0) 2021.01.01
Unity Shader에 대한 이해  (0) 2021.01.01

wiki.polycount.com/wiki/VertexNormal#Editing_Normals_in_3ds_Max

 

VertexNormal - polycount

Vertex normals are invisible lines pointing out of a 3D model's surface, at each vertex. The game compares these normals against a light's direction. If the light is directly facing a normal, the surface is brightest there. When a normal is facing away fro

wiki.polycount.com

youtu.be/R-Zxzq49wCg

 

1. 레이어에 선택한 오브젝트가 없는 경우가 종종 있습니다.

2. 오브젝트를 누른후 익스플로러 하단에 아이콘을 선택하면 선택된 오브젝트가 나옵니다.

3. 우클릭하여 새로운 레이어에 추가하면 레이어가 생기면서 나타납니다.

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NPC_Chair_Random : StateMachineBehaviour
{
    // OnStateEnter is called before OnStateEnter is called on any state inside this state machine
    //override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    //{
    //    
    //}

    // OnStateUpdate is called before OnStateUpdate is called on any state inside this state machine
    //override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    //{
    //    
    //}

    // OnStateExit is called before OnStateExit is called on any state inside this state machine
    //override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    //{
    //    
    //}

    // OnStateMove is called before OnStateMove is called on any state inside this state machine
    //override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    //{
    //    
    //}

    // OnStateIK is called before OnStateIK is called on any state inside this state machine
    //override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    //{
    //    
    //}

    // OnStateMachineEnter is called when entering a state machine via its Entry Node
    override public void OnStateMachineEnter(Animator animator, int stateMachinePathHash)
    {
        animator.SetInteger("MoveID", Random.Range(0, 2)); //""따옴표 때문에 에러가 나서 헤멤.
    }

    // OnStateMachineExit is called when exiting a state machine via its Exit Node
    //override public void OnStateMachineExit(Animator animator, int stateMachinePathHash)
    //{
    //    
    //}
}

'Unity > C#' 카테고리의 다른 글

LayerChanger  (0) 2021.06.08
물체의 랜덤 스케일  (0) 2021.01.04
재미로 만들어보는 유니티(콘솔) 로또  (0) 2020.12.29
유리가 깨지는 연출  (0) 2020.12.15
Sin, Cos, Tan  (0) 2020.12.15