2016년 9월 4일 일요일

[판교 맛집] - 고메부인의 한우와 더탭하우스의 IPA맥주

아다시피 몇년째 주말에 일을 하고 있다

최근에는 판교에서 관계자들이 모이기 때문에

매주 토요일에는 판교에 있게 된다

지난주에는 일이 4시쯤 끝나서 정진호 대표님을 꼬드겨 술을 한잔 했다

아다시피 판교는 5시에 저녁오픈을 하기 때문에 4시는 정말 애매한 시간이다

정대표님이 미국 출장갔다가 IPA(India Pale Ale) 꽂히는 통에

맥주집을 찾고 있었는데, 마침 그 가게가 영업시작 전이었다.

이 집은 결국 나중에 2차로 가게 되었는데, 그 가게가 바로 더 탭 하우스라는 곳이다

H스퀘어 N동 120호라고 하는데, 걍 1층 구석탱이에 있다

삼환하이펙스에서 H스퀘어로 넘어가는 육교 바로밑에 위치하고 있다

이 가게에 대한 자세한 정보는 이곳을 참고하기 바란다.

맥주를 극렬하게 거부하는 내가 이곳의 맥주맛에 반했을 정도니 뭐 ㅋㅋㅋ

IPA맥주라는 것이 일반 맥주보다 알콜도수가 높아서 나에게는 딱 맞았다

솔직히 내가 맥주를 안먹는 이유는 맛이 없어서다

배만 부른 보리차를 왜 마시는지 잘 모르겠더라

근데, 이곳의 맥주라면 기꺼이 마셔줄만 했다

IPA계열 맥주 메뉴

커피 IPA

모자이크 IPA


결국 입맞에 맞는 맥주는 딜리셔스 IPA로 판명 ㅋㅋㅋ


근데, 어쩌다보니 2차 얘기가 먼저 나와버렸네 ㅋㅋ

암튼 1차는 U스페이스 2층의 고메부인이었다

여기가 특이한 것은 숙성시킨 고기를 쓴다는 것

먹어보니 육질이 굉장히 특이한데,

등심님

등심의 상태가 너무 좋아서 살치살과 구분을 못함 ㅎㄷㄷ

굽굽

뒤집뒤집

정갈한 반찬

고기를 구워보니 내부는 부드럽고, 겉은 살짝 질긴 식감이었다

물론 초반에 숯불이 많이 약해서 고기가 제대로 구워지지 못했다

아...슬펐다...고기굽기에 실패하다니 ㅠㅠ

이 집의 유일한 단점이 있다면 약한 숯불이다 

소고기는 강한 화력이 필수다!



암튼 이날은 주말이라 손님이 우리밖에 없었다

처음에는 세트를 주문했는데, 추가로 주물할때는 더 좋은것으로 주문하고 싶었다

정진호 대표 : "한점을 먹도라도 좋은걸로 먹읍시다. 남길때 남기더라도"

잠시후 주방장님이 나오셔서 손님들의 그 한마디가 너무 맘에 든다면서 고기에 대해서 본인의 지식을 풀어 놓으신다

25년 동안 한길을 걸어오셨는데, 정말 고기에 대한 지식이 해박하셨다

업진살과 살치살

이 업진살은 반칙이었습니다

이게 어디가 업진살이라는게냐


게다가 나중에 나온 사장님 특제 삼겹살은 정말 예술이었다

난 이런 삼겹살 첨 먹어봤다 ㅋㅋㅋ

삼겹살입니다

뼈부위 갈비살을 갈로 저며서 만든 삼겹살


암튼, 업진살과 살치살이 나왔는데, 이 녀석들은 입속에 들어가니 식감이 장난이 아니더라

원래 나는 소고기가 지방의 마블링이 많아서 입속에 들어가면 녹는게 좋은건줄말 알았는데

고기의 담백함과 지방의 고소함이 적절하게 잘 어울린다는 것은 또 다른 맛의 세계였다

새롭게 배웠습니다


제주식 갈치속젓(!)을 여기서 볼 줄이야!

사장님과 주방장님 등 그곳 직원분들이 식사하느라 끓인 육계장
본인들만 드시기 미안하다고 대접으로 하나 퍼서 주셨음
근데...후후...미친 맛이었음...
여기 육계장집 오픈하면 손님들 빨아들이는 블랙홀 될 듯
소주에는 역시 탕인듯 ㅋㅋㅋㅋㅋ




2016년 8월 14일 일요일

[자작요리] 블루베리 스파이더 도넛

오늘 만든 블루베리 스파이더 도넛의 자태



[요리시작]

일단은 언더테일에 나오는 스파이더 도넛을 만들어보기 위해 레시피를 열심히 따라함

그럭저럭 초반에는 비쥬얼이 비슷했으나...



블루베리 시럽을 써야하는데, 블루베리를 직접 갈아서 사용한 것이 화근이었을까?



내가 오늘 블루베리를 갈아넣은 것인가? 스머프를 갈아 넣은 것인가? 헷깔리시 시작

이게 컬러 보정따위 하지 않은 순수한 아이폰 카메라의 색감 그대로 찍은 반죽상태임

이대로 구우면 정말 외계생명체가 연성될것 같은 비쥬얼의 반죽이 나와버림

역시나 구워진 후에는 비쥬얼 대참사






도넛을 구웠는데 거대 곰팡이가 연성됨

대체 뭐랑 등가교환된거지?

나도 모르는 고르곤졸라 치즈가 들어갔었나?

암튼, 이 모든것이 블루베리가 만들어낸 대 참사





그러나, 찐하게 쫄인 블루베리 시럽으로 표면 떡칠 마무리해서 훈훈한 비쥬얼로 재탄생

생긴거보다 맛은 꽤 괜찮음 ^^
























2016년 4월 19일 화요일

[자작요리] 쏘세지정식, 바나나푸딩, 초코푸딩

쏘세지 야채볶음, 삶은 쏘세지로 만든 쏘세지 정식


바나나 우유로 만든 바나나푸딩
(냉장고를 부탁해의 미카엘 레시피 참고)


초코 우유로 만든 초코푸딩

미카엘의 레시피에 델리민주 바나나푸딩 기법을 섞음

미카엘 레시피로 만든 푸딩을 바닥에 깔고

오레오 쿠키 올리고

생크림+설탕을 쳐서 거품을 만들어 푸딩과 섞고

오레오를 덮고

과일(사과)을 올리고

생크림을 올리고

오레오를 올리고

과일을 올리고

반복...

냉장고에 한참동안 차갑게 했다

엄청나게 맛있다

미칠듯이 맛있다


2016년 4월 18일 월요일

[자작요리] 클램 차우더

드디어 오늘 병원을 퇴원(탈출)했다.

지난주 목요일부터 입원했으니 4박 5일인 셈이다.

병원에서 4일을 계속 굶고 5일째에 죽만 먹다 퇴원한 터라 뭔가 원기를 회복할 것이 필요했다.

그때 문득 든 생각이 예전에 먹어본 기억이 있는 클램 차우더였다.

조개를 베이스로 만든 스프였는데, 바게트를 찍어 먹으면 그 맛이 정말 그만이었다.

레시피를 뒤져보니 만들기도 쉬워보였다.

12시쯤 퇴원하고 버스타고 집에 오는길에 집앞 GS마트에 들러서 재료를 샀다.

재료를 사가지고 집까지 오는 길이 왜이렇게 힘들던지...

정말 체력이 바닥을 찍었더라.

재료 : 우유, 버터, 밀가루, 양파, 감자, 버섯, 베이컨, 조개
(원래는 바지락으로 국물을 내서 써야하지만 집에 맛조개탕 패키지가 있어서 그걸 사용)

1. 양파, 감자, 버섯, 베이컨을 잘게 썬다.
2. 프라이팬에 버터를 녹이고 재료들을 넣고 볶는다.
3. 양파가 갈색이 될때쯤 조개탕 국물을 살짝 잠길만큼 부어서 타지 않게 끓인다.
4. 냄비에 버터를 녹이고 이후 밀가루를 넣어서 루를 만든다.
5. 조개탕 국물과 조개를 냄비에 넣는다.
6. 프라이팬의 재료를 냄비에 붓는다.
7. 우유를 적당량 붓는다.
8. 마지막으로 버터를 손가락 한마디 정도 넣어주고 끓인다.

그렇게 만든게 이것...

생긴건 초라한데 맛은 놀라웠다.

우유와 양파의 달콤함 + 버터의 풍미 + 조개의 짭짤함 + 버섯의 고소함 + 감자의 식감이 잘 어우러진 물건이 나왔다.

허기지면서도 항생제로 지쳐버린 속을 달래는데 적절한 음식이었다.

게다가 먹다보니 그리운 맛이 나더라.

.
.
.


경기도 파주에 가면 프로방스( http://provence.co.kr ) 라는 곳이 나온다.
그 바로 옆에 영어마을이 있는데, 최근 프로듀스101이 그 영어마을에서 찍고 있어서 참 반가웠더랬다.


프로방스에 가면  꼭 먹었던 메뉴가 있다.


그것은 바로 양송이 크림스프!
어떤 메뉴를 주문하더라도 스프는 반드시 양송이 크림스프였다.

그 이유는 내가 지금까지 먹어본 스프중에서 가장 맛있는 스프였다.

어느 곳을 가봐도 그 맛을 도저히 따라가지 못하더라.

그런데, 오늘 비슷한 맛을 느낄 수 있었다.

양송이를 넣기는 했지만 정말 닮은 스프가 나와버렸다.

오랜만에 느껴보는 맛이었다.

그러고보니 옛날에는 참 자주 찾던 곳인데, 언제부턴가 발길을 끊게 되었군.

그리운 맛이었다.

2015년 11월 27일 금요일

Unity 서피스 셰이더에서 discard나 return을 사용할때 주의할 점

사내 프로젝트에서 요상한 문제를 겪었다.

다른 폰에서는 별다른 문제가 없는데, 유독 Galaxy S4(초기모델)에서만 픽셀이 깨지는 현상이 발견된 것이다.

처음에는 셰이더의 Spec 연산시에 음수(-)값이 나오는 것이 아닌가 하는 문제로 좁혀져서 각종 벡터연산에 saturate()를 집어넣는 방식으로 해결하려 했지만 결국 버그가 잡히지 않았다. 게다가 알파채널이 있는 경우에만 발생하는 것도 이상했다.

그러는 가운데, Galaxy S4초기 모델의 특징은 PowerVR이 사용되었다는 것에 착안하고 구글링을 해보니 유사한 현상이 Stackoverflow에 보고된 사례를 접하게 되었다.

내용을 읽어보면 PowerVR의 병렬처리 구조상 if()문 내에서 discard나 return문이 있을 경우에 원치않는 statement가 처리될 수도 있다는 것이다.

예를 들어서 우리의 경우 mask텍스처의 b채널에 alpha정보를 보관하고 있었기에 다음과 같이 처리를 하였다.


inline void surf (Input IN, inout SurfOut o)
{
   fixed4 mask = tex2D(_MaskMap, IN.uv_MainTex);
if( mask.b <= _Cutoff )
discard;

fixed4 main = tex2D(_MainTex, IN.uv_MainTex);
fixed4 n = tex2D(_BumpMap, IN.uv_MainTex);
        .
        .
        .
}

이렇게 코딩하면 오류가 발생한다는 것이다.

이 코드를 바로 잡으려면

inline void surf (Input IN, inout SurfOut o)
{
        fixed4 mask = tex2D(_MaskMap, IN.uv_MainTex);
if( mask.b <= _Cutoff )
        {
discard;
        }
        else
        {
         fixed4 main = tex2D(_MainTex, IN.uv_MainTex);
           fixed4 n = tex2D(_BumpMap, IN.uv_MainTex);
                .
                .
                .
        }
}

이렇게 해야 GPU의 병렬처리시에 오류를 막을 수 있다.

if() {}블록 다음에는 반드시 else {}블록으로 처리를 해야만 GPU가 제대로 지원한다는 것을 명심하자. 

2015년 11월 20일 금요일

[자작요리] 굴짬뽕 맛이 나는 나가사키 짬뽕 만들기

주말에 집에 혼자 있다가 냉장고를 기웃거려보니 바지락 남은 것이 있더라.

그래서, 급요리 모드로 변경해서 뚝딱 뚝딱 짬뽕을 끓여봤음

최종 완성버전의 비쥬얼


그럼 이제 조리 과정을 살펴보자 ㅋㅋㅋㅋㅋ
먼저 재료!

오늘의 주재료

오늘의 부재료
일단 바지락은 필수, 마늘, 양파, 청양고추는 my favorite vegetables.


먼저 마늘을 기름에 볶아서 마늘향을 기름에 입힌다

이제 야채를 볶으면 야채에 마늘향이 충분히 스며든다

소금간은 필요없고 청양고추와 통후추로 간단히 매운맛과 향을 추가한다

바지락 투하

쉐낏쉐낏 볶아주면 바지락 뚜껑이 열림
내가 바지락을 화나게 한건가?

물 600밀리를 붓고(설명서는 500이지만 난 재료를 추가했으니 물도 추가)

보글 보글 끓으면 스프추가

드디어 면 투척!

면은 공기와 자주 접촉할수록 탱글한 식감이 살아남

혼자 먹을 것이니 가급적 가장 크고 아름다운 그릇을 찾는다
혼자 있을때야말로 식구들의 간섭없이 최대한 우아하게 먹어보자

비쥬얼은 그럴듯하다

오~ 면발이 살아있군
게다가, 이 맛은...중국식 굴짬뽕 맛이다!
왜 굴짬뽕 맛이 나냐고 물으신다면 굴짬뽕맛이 나서....
바지락이나 굴이나 같은 어패류니까 그러려니 함

밥을 말아먹지 않을 수 음슴

결국 국물까지다 먹음
저 멀리 바지락의 조개무덤이 보임

다음엔 나가사키 홍짬뽕에 도전해 보겠음.
오늘은 마늘 기름으로 맑은 짬뽕의 깊은 국물맛을 내봤지만,
다음에는 고추기름을 만들어서 미칠듯한 매운맛을 구현해 보겠음. ㅋㅋ



2015년 8월 30일 일요일

[유니티 최적화 기법] - 셰이더 Variants

유니티 셰이더를 작성할 때 쉽게 간과하는 것이 있다.

다음은 흔한 셰이더 코드다. 빨간색 부분을 보자.
Shader "Toon/PMO_toon_mask_skin" {
    Properties {
         _Color ("Main Color", Color) = (1.0, 1.0, 1.0, 1.0)
         _UnderTex ("Under (RGB)", 2D) = "white" {}
         _MainTex ("Skin (RGB)", 2D) = "white" {}
         _RimPower ("Rim Power", Range(0.5,8.0)) = 2.0
         _RimIntesity ("Rim Intensity", float) = 2.0
         _ColorIntensity("Skin Intensity", float) = 1
         _PickColor ("Pick Color", Color) = (1, 1, 1, 1)
     }
  
     SubShader {
         Tags {"RenderTexture" = "RenderTextureMask" "IgnoreProjector"="True" "RenderType"="Opaque"}
         LOD 200
         
         CGPROGRAM
         #pragma surface surf ToonRampFace
 
         sampler2D _UnderTex;
         sampler2D _MainTex;
         half4     _Color;
         half      _RimPower;
         half4     _PickColor;
         half      _RimIntesity;
         half      _ColorIntensity;
 
         struct Input
         {
             half2 uv_MainTex : TEXCOORD0;
             half3 viewDir;
         };

         struct SurfOut
         {
             half3 Albedo;
             half3 Normal;
             half3 Emission;
             half  Specular;
             half  Alpha;
             half3 viewDir;
         };

         #pragma lighting ToonRampFace exclude_path:prepass
         inline half4 LightingToonRampFace (SurfOut s, half3 lightDir, half atten)
         {
             half4 c;
             half rim = 1.0 - saturate(dot (normalize(s.viewDir) , s.Normal));
             c.rgb = (s.Albedo * _LightColor0.rgb + _PickColor.rgb * _LightColor0.rgb * pow (rim, _RimPower) * _RimIntesity)  * atten;              
             c.a = s.Alpha;
             return c;
         }
   
         void surf (Input IN, inout SurfOut o) 
         {                      
             half4 skin = tex2D(_MainTex, IN.uv_MainTex) * _Color;
             half4 under = tex2D(_UnderTex, IN.uv_MainTex) * _Color;
             if(under.a > 0.48f)
             {
                o.Albedo = under.rgb * under.a * _ColorIntensity + (1.0f - under.a) * skin.rgb;
             }
             else
             {
                o.Albedo = skin.rgb * _ColorIntensity;
             }          
            
             o.Alpha = skin.a;
             o.viewDir = IN.viewDir;            
         }
 
         ENDCG
    }
    FallBack "Diffuse"
}
[코드-1] 흔한 Surface 셰이더 코드

보다시피 흔히 알고 있는 Surface셰이더를 사용중이며, #pragma를 사용해서 각종 컴파일 규칙을 정의해주고 있다.

이 셰이더는 컴파일될 때 과연 어떻게 될까?

유니티의 셰이더코드는 PC의 것과 매우 다르다. PC는 알파의 유무, 뼈대의 개수, 라이트의 개수, 라이맵의 유무 등에 따라서 각각의 경우마다 셰이더를 따로 작성해야 했고, 이를 감당할수 없게 되었을때 우리는 셰이더 폭발(!)이라고 불렀다. 유니티를 사용해보면 이런 부분들이 매우 편하게 되어 있어서 더 이상 셰이더 폭발을 걱정할 필요가 없을 줄 알았다.

특히 Surface셰이더를 사용하면 CgHLSL을 직접 사용한 코딩보다 훨씬 강력하게 지원되기 때문에 즐겨 사용하게 된다. 문제는 이러한 지원이 너무나 강력하다보니 원치 않는 부작용이 나타난다는 것이다.

유니티에서는 이러한 알아서 제멋대로 강력함을 최소화하기 위해서 #pragma 명령어로 다양한 제어를 할 수 있게 해놓았다. 만약 light probe를 원치않으면 novertexlights를 추가하면 된다.

#pragma surface surf ToonRampFace novertexlights

이렇게 하면 light probe 기능이 없는 셰이더 코드를 생성해주며, 당연히 Light probe코드가 제거되었기 때문에 셰이더 코드가 훨씬 가벼워진다. #pragma 명령어와 관련된 다양한 옵션은 매뉴얼(http://docs.unity3d.com/Manual/SL-SurfaceShaders.html) 을 참고하도록 하자.

오늘 말하고자 하는 것은 의외로 간과하게 되는 유니티에서의 셰이더 폭발에 관한 것이다

사실 모바일(유니티)에서도 셰이더 폭발은 발생한다. 우리가 그것을 잘 모르고 있을 뿐이다. [그림-1]을 보도록 하자.

[그림-1] 셰이더 코드의 Inspector화면

제일 하단의 Variants값이 14로 되어 있는데, 이것이 의미하는 것은 바로 옆의 [Show]버튼을 눌러보면 알 수 있다.

// Total snippets: 2
// -----------------------------------------
// Snippet #0 platforms ffffffff:

9 keyword variants:

DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_OFF
DIRECTIONAL LIGHTMAP_ON DIRLIGHTMAP_OFF SHADOWS_OFF
DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_SCREEN
DIRECTIONAL LIGHTMAP_ON DIRLIGHTMAP_OFF SHADOWS_SCREEN
DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_OFF VERTEXLIGHT_ON
DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_SCREEN VERTEXLIGHT_ON
DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_SCREEN SHADOWS_NATIVE
DIRECTIONAL LIGHTMAP_ON DIRLIGHTMAP_OFF SHADOWS_SCREEN SHADOWS_NATIVE
DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_SCREEN SHADOWS_NATIVE VERTEXLIGHT_ON


// -----------------------------------------
// Snippet #1 platforms ffffffff:

5 keyword variants:

POINT
DIRECTIONAL
SPOT
POINT_COOKIE
DIRECTIONAL_COOKIE


[코드-2] 변종 셰이더 코드의 종류

이것이 의미하는 것이 무얼까?

PC에서 셰이더를 개발해본 사람은 단박에 알 수 있을 것이다. 라이트맵이 있는 경우, 없는 경우, 그림자가 있는 경우 없는 경우, 정점조명이 있는 경우, 없는 경우 등등에 따라서 셰이더 코드를 모두 다르게 만들어야 하고, 이러한 과정 때문에 셰이더 대폭발이라는 참사가 발생하는데, 유니티에서는 사실 우리 눈에 보이지 않았을뿐 내부적으로 폭발이 발생하고 있었던 것이다너무 잘 숨겨놔서 잘 모를뿐이다
저 14라는 숫자는 다시 말해서 나는 비록 셰이더를 1개만 만들었지만, 다양한 경우에 적용될수 있는 변종이 유니티에 의해서 14개 생성되었다는 것이다. 이런 망할 ㅋㅋㅋ

그나마 모바일은 캐릭터 스키닝을 일반적으로 CPU에서 하니까 뼈대 개수에 따른 가중치별 분화는 없어서 다행이랄까? (유니티 4.5에서 GPU 스키닝을 지원하도록 컴파일해보면 몇몇 폰에서 이상 현상을 발생시킨다.)

문제는 이렇게 많은 변종 셰이더가 있을 경우 로딩에 치명적인 악영향을 끼치게 된다. 실제 스테이지를 구성하는 메시, 텍스처, 애니 데이터 로딩 시간을 모두 합친 급에 육박하는 셰이더 로딩이라는 불상사를 직접 격고 나서야 나도 이러한 문제점을 깨달았다.

방법은 의외로 간단하다. 앞서 말한 #pragma를 사용해서 필요 없는 변종들은 생성하지 않도록 지정하는 것이다다음과 같이 변경해보자

변경전: #pragma surface surf ToonRampFace
변경후: #pragma surface surf ToonRampFace nolightmap

 
[그림-2] 줄어든 Variants값

이 상태로 저장하면 [그림-2]처럼 Variants11로 줄어든 것을 목격할 수 있다. [show]버튼을 눌러서 확인해보면 [코드-3]처럼 분기되는 경우의 수가 줄어들어 있다.

// Total snippets: 2
// -----------------------------------------
// Snippet #0 platforms ffffffff:

6 keyword variants:

DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_OFF
DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_SCREEN
DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_OFF VERTEXLIGHT_ON
DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_SCREEN VERTEXLIGHT_ON
DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_SCREEN SHADOWS_NATIVE
DIRECTIONAL LIGHTMAP_OFF DIRLIGHTMAP_OFF SHADOWS_SCREEN SHADOWS_NATIVE VERTEXLIGHT_ON


// -----------------------------------------
// Snippet #1 platforms ffffffff:

5 keyword variants:

POINT
DIRECTIONAL
SPOT
POINT_COOKIE
DIRECTIONAL_COOKIE



이 외에도 줄일 수 있는 여지가 이것 저것 더 있으니 꼭 직접 찾아보기 바란다

지금 이 예의 경우에는 캐릭터 전용 셰이더기 때문에 라이트맵이 필요없었다. 따라서 #pragma를 사용해 라이트맵 지원 셰이더 생성을 막은 것이다. 이처럼 특정 용도로 제한된 셰이더(주로 캐릭터, FX, Post Process)들은 #pragma로 제한을 두어서 변종의 생성을 억제할 필요가 있다