• 소개
  • 저서목록
  • 모든글
  • cat:개발
  • cat:음악
  • cat:개인
  • 그래픽 프로그래밍 팀장이 될 뻔 했었다....

    난 매우 직선적인 성격이다.. 특히 회사에서 일할 땐…. 말도 안되는 개소리는 개소리라고 말해주고… 실력이 없는 놈이 정치를 하려고하면 쌍욕도 잘해준다… 사실 주변에서는 이러면 적만 만들다가 회사 짤리니 조심하란 이야길 하는데… 내 자세는 언제나..

    • 2012-02-07
    • 개발일지
  • 거짓말로 버티고 사는 개발자...

    최근에 회사를 떠나야 했던 떠난 개발자가 있다. 뭐 짧게 짧게 여러 회사를 옮겨다녀야 하는 인간 중 하나인데…. (뭐, 그래야 하는 이유는 대충 다들 알테고)…. 어쩌다 오늘 그 인간의 블로그를 보게 되었는데 본인이 회사를 떠나게 된 이유를 설명하고 있었다. 나를 비롯한 많은 울 회사 직원들이 이 글을 아주 즐겁게 봤는데… 이게 세계 최고의 판타지 소설 '반지의 제왕'을 연상시키기 때문이라지….?

    • 2012-02-07
    • 게임업계 인생조언 개발일지
  • 유니티에서 topology가 같은 캐릭터간에 애니메이션 공유하기...

    이미지 출처: http://answers.unity3d.com/questions/191282/sharing-animations-between-models.html

    • 2012-02-04
    • unity
  • 새로운 기법 != 새 장난감

    게임데브포에버에 무슨 글을 올릴까 고민을 좀 해봤는데… 그래픽 전문자료들은 이미 다른 필자분들이 열심히 올리고 계셔서 요번에는 그냥 제 경험담을 올리도록 하지요.. (이런 글을 원하시는 분들도 꽤 계실듯…?)

    • 2012-02-01
    • 개발일지 그래픽 shader
  • 포토샵 CS3가 실행중이면 ESC 키가 작동하지 않는 버그 고치기

    포토샵 CS3를 열어두면 윈도우 전역적으로 ESC 키가 먹히지 않는 문제가 있었다. 한마디로 짜증이었던 게지 -_-;;; CS5는 이 문제를 고쳤던데… CS5로 업그레이드 해달라고 회사에 부탁해도 현재 프로젝트에서 쓰는 버전이 CS3이니 그럴수 없단다…

    • 2012-01-31
    • 포토샵
  • [포프의 쉐이더 입문강좌] 06. 만화같은 명암을 입히는 툰쉐이더

    이 장에서 새로 배우는 HLSL

    • 2012-01-30
    • 도서 셰이더강좌 그래픽 shader
  • 디테일맵과 감마보정에 대한 뻘쭘 경험담

    디퓨즈 맵에 디테일 맵을 곱하는 방법은 텍스처 타일링으로 인해 발생하는 반복패턴을 숨길 때 사용할 수 있는 좋은 방법입니다.

    • 2012-01-25
    • 개발일지 그래픽 shader
  • [포프의 쉐이더 입문강좌] 05. 물체에 색을 입히는 디퓨즈/스페큘러 매핑 Part 2

    이전편 보기픽셀쉐이더픽셀쉐이더도 전체 소스코드를 보여드린 뒤, 새로 추가된 내용만 설명 드립니다.struct PS_INPUT{   float2 mUV : TEXCOORD0;   float3 mDiffuse : TEXCOORD1;   float3 mViewDir: TEXCOORD2;   float3 mReflection: TEXCOORD3;};sampler2D DiffuseSampler;sampler2D SpecularSampler;float3 gLightColor;float4 ps_main(PS_INPUT Input) : COLOR{   float4 albedo = tex2D(DiffuseSampler, Input.mUV);   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 )   {      specular = saturate(dot(reflection, -viewDir ));      specular = pow(specular, 20.0f);         float4 specularIntensity  = tex2D(SpecularSampler, Input.mUV);      specular *= specularIntensity.rgb * gLightColor;   }   float3 ambient = float3(0.1f, 0.1f, 0.1f) * albedo;   return float4(ambient + diffuse + specular, 1);}우선 새로 렌더몽키에 추가했던 세 변수를 전역적으로 선언하겠습니다.sampler2D DiffuseSampler;sampler2D SpecularSampler;float3 gLightColor;그리고 PS_INPUT구조체에 UV좌표를 추가합니다.  float2 mUV : TEXCOORD0;이제 픽셀쉐이더 함수의 젤 윗줄에서 디퓨즈맵을 샘플링 해보죠.   float4 albedo = tex2D(DiffuseSampler, Input.mUV);이것이 바로 현재 픽셀이 반사하는 색깔입니다. 여기에 난반사광의 양과 빛의 색상을 곱해야 한다고 했죠? 이전에 diffuse변수를 구하던 코드를 다음과 같이 바꿉니다.   float3 diffuse = gLightColor * albedo.rgb * saturate(Input.mDiffuse);이제 한번 F5를 눌러서 정점쉐이더와 픽셀쉐이더를 각각 컴파일 한 뒤, 미리 보기 창을 한 번 봐볼까요?그림 5.3. 디퓨즈맵만 적용한 결과담벽 텍스처가 보이죠? 푸르스름한 빛도 보이네요. 근데 스페큘러맵을 아직 쓰지 않아서인지 정 반사광이 너무 강하네요. 돌 사이의 틈새까지도 말이지요! 그럼 스페큘러맵을 더해보도록 하죠.팁: 미리 보기 창에서 물체를 회전하는 법그림 5.3 처럼 틈새에 빛이 들어오게 하려면 물체를 회전하셔야 할 겁니다. 미리 보기 창에서 물체를 회전하시려면 창 안에 왼쪽 마우스 버튼을 누른 채 마우스를 이리저리 움직여보세요. 만약 회전 대신에 이동이나 확대/축소가 된다면 툴바에서 오른쪽 두 번째 아이콘(Overloaded Camera Mode)을 눌러주시면 됩니다.픽셀쉐이더에서 specular 변수의 거듭제곱을 구하는 코드(pow함수 호출) 바로 밑에서 스페큘러맵을 샘플링 합니다.      float4 specularIntensity  = tex2D(SpecularSampler, Input.mUV);이제 이것과 빛의 색상을 specular에 곱해야겠죠? 코드는 다음과 같습니다.      float4 specularIntensity  = tex2D(SpecularSampler, Input.mUV);      specular *= specularIntensity.rgb * gLightColor;위 그림에서 또 다른 문제점 하나는 난 반사광이 사라지는 순간부터 디퓨즈 텍스처의 디테일도 사라진다는 것입니다. 이것은 주변광 값으로 (0.1, 0.1, 0.1)만을 사용했기 때문인데요. 주변광은 그냥 저희가 임의로 정한 빛의 양이므로 여기에도 디퓨즈맵을 곱해주는 것이 맞습니다. ambient변수를 구하는 코드를 찾아 다음과 같이 바꿔주세요.float3 ambient = float3(0.1f, 0.1f, 0.1f) * albedo;다시 한번 정점쉐이더와 픽셀쉐이더를 컴파일 한 뒤 미리 보기 창을 볼까요?그림 5.4. 스페큘러맵과 주변광까지 제대로 적용한 결과확실한 차이를 볼 수 있죠? 정 반사광이 그렇게 강하지도 않고, 틈새도 완벽하네요. 거기다가 어두운 픽셀에서도 디퓨즈맵의 흔적을 찾아 볼 수 있네요.선택사항: DirectX 프레임워크이제 C++로 작성한 DirectX 프레임워크에서 쉐이더를 사용하시려는 분들을 위한 선택적인 절입니다.우선 저번 장에서 사용했던 프레임워크의 사본을 만들어 새로운 폴더에 저장합니다. 그 다음, 렌더몽키에서 사용했던 쉐이더와 3D 모델을 DirectX 프레임워크에서 사용할 수 있도록 파일로 저장합니다. Sphere.x와 SpecularMapping.fx라는 파일이름을 사용하도록 하겠습니다. 또한 렌더몽키에서 사용했었던 텍스처 2개를 복사해다가 프레임워크 폴더에 저장합니다. Fieldstone_DM.tga와 Fieldstone_SM.tga로 이름을 사용하지요.이제 비주얼 C++ 솔루션 파일을 연 뒤, 소스코드에서 gpLightingShader 변수가 언급된 곳을 모두 찾아gpSpecularMappingShader로 변경합니다.그 다음, 전역변수 섹션에 가서 두 텍스처를 저장할 포인터들과 빛의 색상을 저장하는 변수를 선언합니다.// 텍스처LPDIRECT3DTEXTURE9        gpStoneDM    = NULL;LPDIRECT3DTEXTURE9        gpStoneSM    = NULL;// 빛의 색상D3DXVECTOR4               gLightColor(0.7f, 0.7f, 1.0f, 1.0f);렌더몽키에서 사용했던 푸르스름한 빛의 값인 (0.7, 0.7, 1.0)을 그대로 사용하는 거 보이시죠? 위에서 새로운 D3D 자원(텍스처)을 둘 선언했으니 이들을 해제하는 코드를 추가하도록 하죠. CleanUp() 함수에 다음의 코드를 추가합니다.    // 텍스처를 release 한다.    if ( gpStoneDM )    {        gpStoneDM->Release();        gpStoneDM = NULL;    }    if ( gpStoneSM )    {        gpStoneSM->Release();        gpStoneSM = NULL;    }이제 D3D자원들을 로딩할 차례입니다. LoadAssets() 함수에 다음의 코드를 더합니다.    // 텍스처 로딩    gpStoneDM = LoadTexture("Fieldstone_DM.tga");    if ( !gpStoneDM )    {        return false;    }    gpStoneSM = LoadTexture("Fieldstone_SM.tga");    if ( !gpStoneSM )    {        return false;    }쉐이더 파일의 이름을 SpecularMapping.fx로 바꿔주는 것도 잊지 맙시다.    gpSpecularMappingShader = LoadShader("SpecularMapping.fx");이제 마지막으로 RenderScene() 함수를 봅시다. 이미 쉐이더가 모든 일을 하고 있으니 간단히 새로운 변수들을 대입해주기만 하면 되겠네요. 예전에 SetMatrix() 함수들을 호출 해주던 곳이 있었죠? 그 아래에 다음의 코드를 추가합시다.    gpSpecularMappingShader->SetVector("gLightColor", &gLightColor);    gpSpecularMappingShader->SetTexture("DiffuseMap_Tex", gpStoneDM);    gpSpecularMappingShader->SetTexture("SpecularMap_Tex", gpStoneSM);위 코드는 빛의 색상과 두 텍스처맵을 쉐이더에 전달해 줍니다. 텍스처맵을 대입해 줄 때 _Tex 접미사를 붙여줘야 한다는 건 '제3장: 텍스처매핑'에서 설명했었죠?이제 코드를 컴파일 한 뒤, 프로그램을 실행하면 렌더몽키에서와 동일한 결과를 보실 수 있을 겁니다.이쯤 되면 느끼셨겠지만 쉐이더를 사용하면 DirectX 프레임워크에서 책임져야 할 그래픽 관련 업무가 현저히 줄어듭니다. D3D 자원을 로딩하는 것과 쉐이더 매개변수, 그리고 렌더상태(render state)를 관리하는 것이 거의 전부입니다.정리다음은 이 장에서 배운 내용을 짧게 요약해 놓은 것입니다.인간이 물체의 색을 볼 수 있는 이유는 물체마다 흡수 및 반사하는 빛의 스펙트럼이 다르기 때문이다.3D 그래픽에서는 디퓨즈맵과 스페큘러맵을 사용하여 빛의 흡수 및 반사를 재현한다.스페큘러맵은 각 픽셀의 정 반사광을 조절하는 것을 주 목적으로 한다.빛의 색도 물체의 최종 색에 기여한다.텍스처는 색상정보만을 저장하는 것이 아니다. 스페큘러맵의 경우가 그 예이다.이 장은 예상보다 매우 쉽게 끝나버렸습니다. 저번 장에서 작성했던 조명쉐이더에 살을 붙였기 때문인데요. 이렇게 기본이 되는 쉐이더를 잘 짜놓으면 매우 쉽게 구현할 수 있는 기법들이 많습니다.하지만 이번 장에서 배운 내용을 절대 가볍게 보시지 말기 바랍니다. 최근 게임에서 3D 물체를 렌더링 할 때 여기서 배웠던 기법을 법선매핑(법선매핑(normal mapping)은 제7장에서 배웁니다)과 혼합하는 것이 거의 표준입니다.다음편 보기

    • 2012-01-23
    • 도서 셰이더강좌 그래픽 shader
  • KGC 2011 강연자료 공개후 국/내외 반응

    뒤져보니 KGC 2011 발표자료를 공개한 뒤에 받은 피드백을 모아놓은 게 있었는데 깜박잊고 안올렸네요. 저 번에 블로그에 올렸던 강연 들으신 분의 피드백은 중복을 막기 위해 생략…

    • 2012-01-18
    • 발표 그래픽 shader
  • [포프의 쉐이더 입문강좌] 05. 물체에 색을 입히는 디퓨즈/스페큘러 매핑 Part 1

    이전편 보기샘플파일 받기제5장 물체에 색을 입히는 디퓨즈/스페큘러 매핑실 세계에서 물체들이 다른 색을 갖는 이유는 물체마다 흡수/반사하는 빛의 스펙트럼(spectrum)이 다르기 때문입니다. 예를 들면 검정색 표면은 모든 스펙트럼을 흡수해서 검정색이고, 하얀색 표면은 모든 스펙트럼을 반사해서 하얀색입니다. 빨간색 표면 같은 경우는 빨강색의 스펙트럼을 반사하고 그 외의 스펙트럼을 흡수하니 빨간색으로 보이는 것이죠.그렇다면 표면이 빛을 흡수하는 성질을 쉐이더에서 어떻게 표현할까요? 표면 전체가 한가지 색으로 칠해져 있다면 그냥 간단히 전역변수를 사용하면 되겠죠? 하지만 대부분의 경우, 물체의 표면은 다소 복잡한 패턴을 가지고 있습니다. 따라서 각 픽셀마다 색상을 정해줘야겠지요. 그럼 표면에서 반사할 색을 이미지로 그린 뒤, 픽셀쉐이더에서 이 텍스처를 읽어와 조명계산의 결과에 곱하면 되겠죠?그런데 '제4장: 기초적인 조명쉐이더'에서 빛을 계산할 때, 난 반사광(diffuse light)와 정 반사광(specular light)을 따로 구했었죠? 그렇다면 난 반사광과 정 반사광을 합친 결과에 이 텍스처를 곱해야 할까요? 아니면 따로 해야 할까요? 전에도 말씀드렸듯이 인간이 물체를 지각할 수 있는 이유는 대부분 난 반사광 덕분입니다. (정 반사광은 타이트한 하이라이트를 추가해줄 뿐이지요.) 따라서 위 텍스처를 난 반사광의 결과에만 적용하는 것으로 충분합니다. 이렇게 난 반사광에 적용하는 텍스처를 디퓨즈맵(diffuse map)이라 부릅니다.그렇다면 정 반사광은 어떻게 할까요? 물론 디퓨즈맵을 정 반사광에 그대로 사용할 수도 있습니다만 다음과 같은 두 가지 이유 때문에 정 반사광용으로 스페큘러맵(specular map)을 따로 만드는 경우가 허다합니다. 첫째, 난 반사광이 반사하는 빛과 정 반사광이 반사하는 빛의 스펙트럼이 다른 경우가 있습니다. 둘째, 각 픽셀이 반사하는 정 반사광의 정도를 조절하는 용도로 스페큘러맵을 사용할 수도 있습니다. 예를 들어, 사람의 얼굴에 정 반사광을 때린다고 생각해 보죠. '제4장: 기초적인 조명쉐이더'에서 봤던 것처럼 얼굴의 전체에서 고르게 정 반사광이 보일까요? 거울을 보시면 알겠지만 이마나 코가 더 반짝거리죠? 그리고 이마나 코에서도 정 반사광이 좀 듬성듬성 보일 겁니다. (이건 모공이나 털 때문에 피부가 매끄럽지 않기 때문입니다.) 스페큘러맵을 잘 칠하면 이런 효과를 낼 수 있습니다. 따라서 이 장에서는 디퓨즈맵과 스페큘러맵을 따로 사용하도록 하겠습니다.이 외에도 물체의 색에 영향을 미치는 다른 요소가 있습니다. 바로 조명의 색입니다. 흰색 물체에 빨간색 빛을 비추면 물체가 불그스름하게 되죠? 조명의 색은 전역변수로 쉽게 지정할 수 있습니다.여태까지 말씀 드린 것을 보기 쉽게 설명하면 다음과 같습니다.난 반사광 = 빛의 색상 X 난 반사광의 양 X 디퓨즈맵의 값정 반사광 = 빛의 색상 X 난 반사광의 양 X 스페큘러맵의 값그러면 위 내용들을 염두에 두고 디퓨즈/스페큘러매핑 쉐이더를 작성해 볼까요?기초설정일단 저번 장에서 사용했던 렌더몽키 프로젝트의 사본을 만들어 새로운 폴더에 저장합니다. 혹시 렌더몽키 프로젝트를 저장해 놓지 않으신 분들은 부록 CD에서 samples\04_lighting\lighting.rfx 파일을 복사해 오시면 됩니다.이 파일을 렌더몽키에서 연 다음, 쉐이더의 이름을 SpecularMapping으로 바꾸겠습니다. 이름까지 바꾸셨다면 이제 디퓨즈맵과 스페큘러맵으로 사용할 이미지들을 추가해야겠군요. 쉐이더 이름에 마우스 오른쪽 버튼을 누르면 나오는 팝업메뉴에서 Add Texture > Add 2D Texture > Fieldstone.tga파일을 선택합니다. 그러면 Fieldstone이라는 이름의 텍스처가 보이시죠? 이 이름을 DiffuseMap으로 바꾸도록 합시다.이제 Pass 0에 마우스 오른쪽 버튼을 눌러 Add Texture Object > DiffuseMap을 선택합니다. Texture0이라는 텍스처 개체가 생겼을 것입니다. 이 이름을 DiffuseSampler로 변경합니다.이제 스페큘러맵을 추가해야 하는데 아무리 렌더몽키 폴더를 뒤져봐도 마땅한 놈이 안 보이는군요. 그래서 제 손으로 직접 스페큘러맵을 만들어서 부록 CD에 넣어놨습니다. 일단 이 스페큘러맵이 어떻게 생겼는지 한번 볼까요? 디퓨즈맵과 같이 비교해서 보면 좋겠군요그림 5.1. 디퓨즈맵(왼쪽)과 스페큘러맵(오른쪽)스페큘러맵에서 돌판 사이의 틈새를 검정색으로 칠해 놓은 거 보이시죠? 따라서 이 틈새는 전혀 정 반사광을 반사하지 않을 겁니다. (하지만 난 반사광은 여전히 존재하지요.) 여기서 한가지 기억하실 점은 텍스처가 언제나 색상정보를 가지지는 않는다는 것입니다. 스페큘러맵이 그 좋은 예죠. 스페큘러맵에 저장된 정보는 최종이미지의 색상 값이라기 보다는 각 픽셀이 반사하는 정 반사광의 양입니다. 이와 마찬가지로 픽셀 수준에서 제어하고 싶은 변수가 있다면 이렇게 텍스처를 사용하는 것이 보통입니다. 후에 법선매핑을 다룰 때, 이렇게 텍스처를 이용하는 예를 보실 수 있을 것입니다.팁: 픽셀수준에서 제어하고 싶은 변수가 있다면 텍스처를 이용합니다.자, 그럼 부록CD에서 Samples\05_DiffuseSpecularMapping\Fieldstone_SM을 찾아서 렌더몽키 프로젝트에 추가합니다. 추가하는 방법은 간단히 파일을 끌어다 이펙트 이름 위에 놓아주면 됩니다. 텍스처 이름은 SpecularMap으로, 텍스처 개체의 이름은 SpecularSampler로 하겠습니다.다음은 빛의 색을 추가하도록 하지요. 쉐이더 이름에 오른쪽 버튼을 누른 뒤에 Add Variable > Float > Float3를 선택합니다. 변수명을 gLightColor로 하지요. 이제 이 변수를 더블클릭하면 값을 대입할 수 있습니다. 약간 푸르스름한 빛을 사용한다는 의미로 (0.7, 0.7, 1.0)을 대입하겠습니다.마지막으로 Stream Mapping을 설정할 차례입니다. '제4장: 기초적인 조명쉐이더'와는 달리 여기서는 텍스처를 사용하니 정점데이터에서 UV 좌표를 읽어와야 합니다. Stream Mapping에 더블클릭을 해서 TEXCOORD0을 추가합니다. 당연히 데이터형은 float2입니다.여기까지 설정을 마치셨다면 렌더몽키 작업공간이 아래와 같을 겁니다.그림 5.2. 기초설정을 마친 렌더몽키 프로젝트정점쉐이더이제 정점쉐이더를 보도록 하지요. 우선 전체 소스코드부터 보여드린 뒤, 새로 추가된 코드만 설명 드리겠습니다.float4x4 gWorldMatrix;float4x4 gViewMatrix;float4x4 gProjectionMatrix;float4 gWorldLightPosition;float4 gWorldCameraPosition;struct VS_INPUT{   float4 mPosition : POSITION;   float3 mNormal: NORMAL;   float2 mUV: TEXCOORD0;};struct VS_OUTPUT{   float4 mPosition : POSITION;   float2 mUV: TEXCOORD0;   float3 mDiffuse : TEXCOORD1;   float3 mViewDir: TEXCOORD2;   float3 mReflection: TEXCOORD3;};VS_OUTPUT vs_main( VS_INPUT Input ){   VS_OUTPUT Output;   Output.mPosition = mul( Input.mPosition, gWorldMatrix );   float3 lightDir = Output.mPosition.xyz - gWorldLightPosition.xyz;   lightDir = normalize(lightDir);     float3 viewDir = normalize(Output.mPosition.xyz - gWorldCameraPosition.xyz);   Output.mViewDir = viewDir;     Output.mPosition = mul( Output.mPosition, gViewMatrix );   Output.mPosition = mul( Output.mPosition, gProjectionMatrix );     float3 worldNormal = mul( Input.mNormal, (float3x3)gWorldMatrix );   worldNormal = normalize(worldNormal);   Output.mDiffuse = dot(-lightDir, worldNormal);   Output.mReflection = reflect(lightDir, worldNormal);   Output.mUV = Input.mUV;     return Output;}새로 추가해야 할 전역변수가 있던가요? 새로 추가된 변수는 빛의 색상하고 2개의 텍스처 샘플러인데 텍스처 샘플러야 당연히 픽셀쉐이더에서 사용하는 거니까 여기선 선언하지 않아도 되겠네요. 빛의 색상도 픽셀쉐이더에서 그냥 곱하면 되겠는걸요?그렇다면 정점쉐이더 입출력 구조체는 어떨까요? 새로 추가해야 할 게 하나 생겼죠? 픽셀쉐이더에서 텍스처매핑을 하려면 UV 좌표가 필요하니까요. 정점버퍼에서 UV 좌표를 가져와서 픽셀쉐이더에 전달해 줘야겠네요. 다음의 코드를 정점쉐이더의 입력구조체와 출력구조체 양쪽에 모두 추가합시다.    float2 mUV: TEXCOORD0;정점쉐이더 함수에 추가해야 할 코드도 딱 한 줄 뿐입니다. UV좌표를 전달해주는 것이죠.   Output.mUV = Input.mUV;정말 간단했죠? 이게 전부랍니다.다음편 보기

    • 2012-01-16
    • 도서 셰이더강좌 그래픽 shader
    • 이전
    • ...
    • 11
    • 12
    • 13
    • 14
    • 15
    • ...
    • 다음
Copyright © 2010 - 2022. Pope Kim
English