외곽선 찾기와 양각효과

 

외곽선찾기

대에충 픽셀의 병도 대비를 이용해 외곽선을 찾는다 인데.....

과정이 뭔소린지 이해가 안된다... 걍 일딴 따라하기 정도로 끝을 내야지.. 잘 모르겠넹....

지난번 세피아 효과에서 세피아 패스만 삭제하고, 변수 추가만 있고 나버진 전부 같다....

흑백 패스에서 픽셀셰이더 코드반 변경.............

 

 

흑백효과  픽셀셰이더 코드

 

struct PS_INPUT{
   float2 mUV : TEXCOORD0;
};


float3x3 Kx = {-1,0,1,
               -2,0,2,
               -1,0,1};
              
              
float3x3 Ky = {1,2,1,
               0,0,0,
             -1,-2,-1};

              
sampler2D SceneSampler;

float2 gPixelOffset;

float4 ps_main(PS_INPUT Input) : COLOR{
  
   float Lx = 0;
   float Ly = 0;
  
   for( int y = -1; y<=1; ++y ){
      for( int x = -1; x <=1; ++x ){
         float2 offset = float2(x,y) * gPixelOffset;
         float3 tex = tex2D(SceneSampler, Input.mUV + offset).rgb;
         float luminance = dot(tex, float3(0.3,0.59,0.11));
        
         Lx += luminance * Kx[y+1][x+1];
         Ly += luminance * Ky[y+1][x+1];
      }
   }
  
   float L = sqrt((Lx*Lx) + (Ly*Ly));
   return float4(L.xxx,1);
}

 

 

결과

 

 

 

 

 

 

 

 

양각효과

위에 패스를 복사해 패스 추가후 수정....이것역시 왹곽선 찻기로 나온 것을 포토샵의 양각효과처럼 표현한것임....

조금은 이해가지만 잘 몰겠심 ㅜㅜ 헐;;

 

 

양각효과 픽셀셰이더 코드

 

struct PS_INPUT{
   float2 mUV : TEXCOORD0;
};


float3x3 K =  {-2,-1,0,
               -1,0,1,
               0,1,2 };
              
              
              
              
sampler2D SceneSampler;

float2 gPixelOffset;

float4 ps_main(PS_INPUT Input) : COLOR{
  
   float res = 0;
  
   for( int y = -1; y<=1; ++y ){
      for( int x = -1; x <=1; ++x ){
         float2 offset = float2(x,y) * gPixelOffset;
         float3 tex = tex2D(SceneSampler, Input.mUV + offset).rgb;
         float luminance = dot(tex, float3(0.3,0.59,0.11));
        
         res += luminance * K[y+1][x+1];
      }
   }
  
   res += 0.5f;
   return float4(res.xxx,1);
}


 

 

 

 

결과

 


 

 

 

셰이더 입문 도 이걸로 끝났다...... 물론 다 이해 한것은 아니지만 이다음으로 공부할 이론과 자주 사용하는 함수를 정리하면서 익히자..... 역시 디자이너는 꺼꾸로 배워야 편한듯 ㅎ;; 공부는 힘들어~

 

 

 

 

 

셰이더 프로그래밍 입문 끝!!!

 

 

 

 

 

 

 

 

 

 

Posted by 프리랜서 디자이너

영상처리 기법 흑백/세피아 사진 만들기

 

정점 셰이더

 

struct VS_INPUT{
   float4 mPosition : POSITION;
   float2 mUV : TEXCOORD0;
};

struct VS_OUTPUT{
   float4 mPosition : POSITION;
   float2 mUV : TEXCOORD0;
};

VS_OUTPUT vs_main (VS_INPUT Input){
   VS_OUTPUT Output;
  
   Output.mPosition = Input.mPosition;
   Output.mUV = Input.mUV;
  
   return Output;
}

 

//처음부터 투영좌표에 메쉬가 생성되어있기 때문에 정점좌표와 uv만 입출력한다.

//책 참고~

 

픽셀 셰이더

 

struct PS_INPUT{
   float2 mUV : TEXCOORD0;
};

sampler2D SceneSampler;

float4 ps_main(PS_INPUT Input) : COLOR{
   float4 tex = tex2D(SceneSampler, Input.mUV);
   return tex;
}

//랜더첵스쳐된  SceneSampler 텍스쳐를 입혀준다.

 

 

 

흑백 만들기 /픽셀 셰이더

 

struct PS_INPUT{
   float2 mUV : TEXCOORD0;
};

sampler2D SceneSampler;

float4 ps_main(PS_INPUT Input) : COLOR{
   float4 tex = tex2D(SceneSampler, Input.mUV);
//   tex.rgb = (tex.r + tex.g + tex.b ) /3;
//   tex.rgb = tex.r * 0.3 + tex.g * 0.59 + tex.g * 0.11;
   tex.rgb = dot(tex.rgb, float3(0.3,0.59,0.11));
   return tex;
}

//흑백으로만들어주는 공식에따라 구현

//dot 공식으로 변경하면 더 빠르다고 함.

 

 

 

 

 

 

 

 

 

세피아 만들기/픽셀 셰이더

 

struct PS_INPUT{
   float2 mUV : TEXCOORD0;
};

sampler2D SceneSampler;

float4 ps_main(PS_INPUT Input) : COLOR{
   float4 tex = tex2D(SceneSampler, Input.mUV);
  
     float4 sepia;
 //  sepia.a = tex.a;
 //  sepia.r = tex.r * 0.393f + tex.g * 0.769f + tex.b * 0.189f;
 //  sepia.g = tex.g * 0.349f + tex.g * 0.686f + tex.b * 0.168f;
 //  sepia.b = tex.b * 0.272f + tex.g * 0.534f + tex.b * 0.131f;
  
   sepia.a = tex.a;
   sepia.r = dot(tex.rgb, float3(0.393f,0.769f,0.189f));
   sepia.g = dot(tex.rgb, float3(0.349f,0.686f,0.168f));
   sepia.b = dot(tex.rbb, float3(0.272f,0.534f,0.131f));
  
   return sepia;
}

//마이크로소프트(?)가 권한 세피아 색만들기 공식으로 구현

//dot공식으로 변경해주면 더 빠르다고함.

 

 

 

 

...다음은...외곽선 찾기와 양각효과.....면 이책도 끝이군.... 그다음엔 자주 사용하는 공삭들 정리해놔야겠네....이론이 부족하니 깊이가 없어;;

 

 

 

 

Posted by 프리랜서 디자이너

그림자 기법을 평정한 그림자매핑

 

 

-요약 이론-

그림자 생성단계

1. 랜더링 결과 (빛을 가로막은 첫번째 물체의 깊이)를 저장할 랜더 타깃을 정해준다.

2. 카메라를 광원 위치에 두고 물체들을 그린다.

3. 픽셀 셰이더에서 빛으로부터 현재 픽셀까지의 깊이를 반환한다.

 

그림자 적용단계

1. 랜더링 결과(일반 장면랜더링)를 화면(백버퍼)에 저장한다.

2. 카메라를 눈 위치에 두고 물체를 그린다.

3. 빛으로부터 현재 픽셀까지의 깊이를 그림자맵에 담겨있는 결과와 비교한다. 현재 깊이가 그림자맵의 깊이보다 크면 그림자를 씌운다.

 

 

 

 

 

그림자만들기위한 정점 셰이더

 

struct VS_INPUT {
   float4 mPosition : POSITION;
};

struct VS_OUTPUT{
   float4 mPosition : POSITION;
   float4 mClipPosition : TEXCOORD1;
};

 

float4x4 gWorldMatrix;
float4x4 gLightViewMatrix;
float4x4 gLightProjectionMatrix;

float4 gWorldLightPosition;

 

 

VS_OUTPUT vs_main(VS_INPUT Input){
   VS_OUTPUT Output;
  
   float4x4 lightViewMatrix = gLightViewMatrix;
  
   float3 dirZ = -normalize(gWorldLightPosition.xyz);
   float3 up = float3(0,1,0);
   float3 dirX = cross(up, dirZ);
   float3 dirY = cross(dirZ, dirX);
  
   lightViewMatrix = float4x4(
      float4(dirX, -dot(gWorldLightPosition.xyz, dirX)),
      float4(dirY, -dot(gWorldLightPosition.xyz, dirY)),
      float4(dirZ, -dot(gWorldLightPosition.xyz, dirZ)),
      float4(0, 0, 0, 1));
   lightViewMatrix = transpose(lightViewMatrix);
  
   Output.mPosition = mul(Input.mPosition, gWorldMatrix);
   Output.mPosition = mul(Output.mPosition, lightViewMatrix);
   Output.mPosition = mul(Output.mPosition, gLightProjectionMatrix);
  
   Output.mClipPosition = Output.mPosition;
  
   return Output;

  
}
//gLightViewMatrix  = 대입할 시멘틱이 없어서 정점 셰이더에서 구현했다고함.

 

 

 

 

 

그림자만들기위한 픽셀 셰이더

 

struct PS_INPUT{
   float4 mClipPosition : TEXCOORD1;
};

 

 

float4 ps_main(PS_INPUT Input) : COLOR
{
  
   float Depth = Input.mClipPosition.z / Input.mClipPosition.w;
   return float4(Depth.xxx,1);
  
}

float4x4 gWorldMatrix;
float4x4 gLightViewMatrix;
float4x4 gLightProjectionMatrix;

float4 gWorldLightPosition;
//동차좌표에 있는 값을 화면상의 좌표값으로 사용하려면 w 값을 1로 바꿔 줘야한다.

 

 

 

 

 

 

 

 

 

그림자 입히기 위한 셰이더-원환체

 

정점 셰이더 코드

 


struct VS_INPUT{
   float4 mPosition : POSITION;
   float3 mNormal : NORMAL;
};

struct VS_OUTPUT{
   float4 mPosition : POSITION;
   float4 mClipPosition : TEXCOORD1;
   float mDiffuse : TEXCOORD2;
};

float4x4 gWorldMatrix;
float4x4 gLightProjectionMatrix;
float4x4 gLightViewMatrix;

float4 gWorldLightPosition;

float4x4 gViewProjectionMatrix;

 

VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;
 
   float4x4 lightViewMatrix = gLightViewMatrix;

   float3 dirZ = -normalize(gWorldLightPosition.xyz);
   float3 up = float3(0,1,0);
   float3 dirX = cross(up, dirZ);
   float3 dirY = cross(dirZ, dirX);
  
   lightViewMatrix = float4x4(
      float4(dirX, -dot(gWorldLightPosition.xyz, dirX)),
      float4(dirY, -dot(gWorldLightPosition.xyz, dirY)),
      float4(dirZ, -dot(gWorldLightPosition.xyz, dirZ)),
      float4(0, 0, 0, 1));
   lightViewMatrix = transpose(lightViewMatrix);

 

 

   float4 worldPosition = mul(Input.mPosition, gWorldMatrix);
   Output.mPosition = mul(worldPosition, gViewProjectionMatrix);

   Output.mClipPosition = mul(worldPosition, lightViewMatrix);
   Output.mClipPosition = mul(Output.mClipPosition, gLightProjectionMatrix);
  
   float3 lightDir = normalize(worldPosition.xyz - gWorldLightPosition.xyz);
   float3 worldNormal = normalize(mul(Input.mNormal, (float3x3)gWorldMatrix));
   Output.mDiffuse = dot(-lightDir, worldNormal);
  
   return Output;
  
}

 

 

 

픽셀 셰이더 코드

 

sampler2D ShadowSampler;
float4 gObjectColor;

struct PS_INPUT{
   float4 mClipPosition : TEXCOORD1;
   float mDiffuse : TEXCOORD2;
};

float4 ps_main(PS_INPUT Input):COLOR
{
   float3 rgb = saturate(Input.mDiffuse ) * gObjectColor;
   float currentDepth = Input.mClipPosition.z / Input.mClipPosition.w;
  
   float2 uv = Input.mClipPosition.xy /Input.mClipPosition.w;
   uv.y = -uv.y;
   uv = uv * 0.5 +0.5;
  
   float shadowDepth = tex2D(ShadowSampler, uv).r;
  
   if(currentDepth > shadowDepth + 0.0000125f){
      rgb *= 0.5f;
   }
  
   return float4(rgb,1.0f);
}

 

 

 

 

 

 

 

 

 

 

다음은...영상처리 기법.. 거의다 했구먼....입문편도.....

 

 

Posted by 프리랜서 디자이너

UV 애니메이션과 울렁효과

 

정점 셰이더

 

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;
};

float gWaveHeight;
float gSpeed;
float gWaveFrequency;
float gUVSpeed;

//uv에니메이션과 울렁 효과를 위한 float 타입의 변수 4개 추가

 

float4x4 gWorldMatrix;
float4x4 gViewMatrix;
float4x4 gProjectionMatrix;
float gTime;

float4 gWorldLightingPosition;
float4 gWorldCameraPosition;


VS_OUTPUT vs_main (VS_INPUT Input){
   VS_OUTPUT Output;
   
   float3 cosTimeX = gWaveHeight * cos(gTime * gSpeed + Input.mUV.x * gWaveFrequency);
   float3 cosTimeY = gWaveHeight * cos(gTime * gSpeed + Input.mUV.y * gWaveFrequency);
   Input.mPosition.xy += cosTimeY + cosTimeX;
    //cos(): 함수를 이용해 uv와 버텍스 애니메이션 구현

    //cosTime  을 하나 더 추가해 y축도 추가로 구현.

   
   Output.mPosition = mul(Input.mPosition, gWorldMatrix);
  
   float3 lightDir = Output.mPosition.xyz - gWorldLightingPosition;
   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 + float2(gTime*gUVSpeed, 0);
  
   return Output;
}

 

 

 

 

 

픽셀 셰이더

 

sampler2D DiffuseSampler;
sampler2D SpecularSampler;

float3 gLightColor;

 

 

struct PS_INPUT{
   float2 mUV : TEXCOORD0;
   float3 mDiffuse : TEXCOORD1;
   float3 mViewDir : TEXCOORD2;
   float3 mReflection : TEXCOORD3;
};

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 spacular = 0;
  
   if( diffuse.x > 0){
      spacular = saturate(dot(reflection,-viewDir));
      spacular = pow(spacular, 20.0f);
     
      float4 specularIntensity = tex2D( SpecularSampler, Input.mUV);
      spacular *= specularIntensity.rgb * gLightColor;
   }
   
   float3 ambient = float3(0.1f, 0.1f, 0.1f) * albedo;

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

 

 

 

 

 

 

*HLSL*

cos() : 코사인 함수

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by 프리랜서 디자이너

입방체 텍스쳐면 있다면

코드 2줄만으로도 만들 수 있는 환경맵핑

 

 

정점 셰이더

 

float4x4 gWorldMatrix;
float4x4 gWorldViewProjectionMatrix;

float4 gWorldLightPosition;
float4 gWorldCameraPosition;

struct VS_INPUT
{
   float4 mPosition : POSITION;
   float3 mNormal: NORMAL;
   float3 mTangent: TANGENT;
   float3 mBinormal: BINORMAL;
   float2 mUV: TEXCOORD0;
};

struct VS_OUTPUT
{
   float4 mPosition : POSITION;
   float2 mUV: TEXCOORD0;
   float3 mLightDir : TEXCOORD1;
   float3 mViewDir: TEXCOORD2;
   float3 T : TEXCOORD3;
   float3 B : TEXCOORD4;
   float3 N : TEXCOORD5;
};

VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;

   Output.mPosition = mul( Input.mPosition, gWorldViewProjectionMatrix );
   Output.mUV = Input.mUV;

   float4 worldPosition = mul( Input.mPosition, gWorldMatrix );
   float3 lightDir = worldPosition.xyz - gWorldLightPosition.xyz;
   Output.mLightDir = normalize(lightDir);
  
   float3 viewDir = normalize(worldPosition.xyz - gWorldCameraPosition.xyz);
   Output.mViewDir = viewDir;
  
   float3 worldNormal = mul( Input.mNormal, (float3x3)gWorldMatrix );
   Output.N = normalize(worldNormal);
  
   float3 worldTangent = mul(Input.mTangent, (float3x3)gWorldMatrix );
   Output.T = normalize(worldTangent);
  
   float3 worldBinormal = mul(Input.mBinormal, (float3x3)gWorldMatrix );
   Output.B = normalize(worldBinormal);
  
   return Output;
}

 

 

픽셸 셰이더

 

struct PS_INPUT
{
   float2 mUV : TEXCOORD0;
   float3 mLightDir : TEXCOORD1;
   float3 mViewDir: TEXCOORD2;
   float3 T : TEXCOORD3;
   float3 B : TEXCOORD4;
   float3 N : TEXCOORD5;
};

sampler2D DiffuseSampler;
sampler2D SpecularSampler;
sampler2D NormalSampler;
samplerCUBE EnvironmentSampler;

float3 gLightColor;

float4 ps_main(PS_INPUT Input) : COLOR
{
   float3 tangentNormal = tex2D(NormalSampler, Input.mUV).xyz;
   tangentNormal = normalize(tangentNormal * 2 - 1)*float3(0,0,1);
//노멀값이 너무 쎄서 float3 값을 곱해줘서 환경맵핑이 잘보이게만들어 준다.

   
   float3x3 TBN = float3x3(normalize(Input.T), normalize(Input.B), normalize(Input.N));
   TBN = transpose(TBN);
   float3 worldNormal = mul(TBN, tangentNormal);
  
   float4 albedo = tex2D(DiffuseSampler, Input.mUV);
   float3 lightDir = normalize(Input.mLightDir);
   float3 diffuse = saturate(dot(worldNormal, -lightDir));
   diffuse = gLightColor * albedo.rgb * diffuse;
  
   float3 viewDir = normalize(Input.mViewDir);

//환경맵에도 카메라벡터를 사용하기위해 if문 밖으로 빼주었다.


   float3 specular = 0;
  
   if ( diffuse.x > 0 )
   {
      float3 reflection = reflect(lightDir, worldNormal);

      specular = saturate(dot(reflection, -viewDir ));
      specular = pow(specular, 20.0f);
     
      float4 specularIntensity  = tex2D(SpecularSampler, Input.mUV);
      specular *= specularIntensity.rgb * gLightColor;
     
   }

 

   float3 viewReflect = reflect(viewDir, worldNormal);

//reflect()함수를 사용해 반사벡터를 구한다.


   float3 environment = texCUBE(EnvironmentSampler, viewReflect).rgb;
//   texCUBE()함수를 이용해 환경맵을 구현한다.


   float3 ambient = float3(0.1f, 0.1f, 0.1f) * albedo;
  
   return float4(ambient + diffuse + specular+environment * 0.5f, 1);

//return에 환경맵을 더해주고 강도를 조절을 위해 *0.5f를 해준다.
}

 

 

#HLSL#

texCUBE() : 입방체 텍스쳐를 샘플링하는 함수

reflect() : 카메라의 반사 벡터를 구하는 함수

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by 프리랜서 디자이너

폴리곤 수를 늘리지 않고도

디테일을 추가할 수 있는 법선 맵핑

 

-이론-

각 픽셀의 법선 정보를 담고있는 텍스쳐를 법선맵(normal map)이라고 한다.

 

법선

법선백터의 경우 -1~0~1 의 값을 가진다 하지만 텍스쳐는 0~1의 값을 갖는다  그때문에 법선벡터의 값을 수식으로 0~1을 가진것 처럼 만들어 준다. 그렇게 해주면 법선 벡터의 0이 텍스쳐에서는 0.5가 되게 만들어 준다.

법선맵 RGB = XYZ x 0.5 + 0.5 

 

법선맵을 법선백터로 바꾸는 공식

법선벡터 XYZ = 법선맵 RGB x 2 - 1  

 

법선공간

법선벡터는 각 표면을 기준으로 벡터의 방향이 결정된다

법선백터를 접선공간, 혹은 표면공간이라고 한다.

 

시멘틱

uv의 u나 v의 축을 접선이라고 부른다.

외적 계산으로 또 하나의 축을 구한다.이것을 종 법선이라고 한다.

법선맵,접선,종법선의 정보를 이미 모델이나 텍스쳐가 자지고있기 때문에 시멘틱을 사용하는 것만으로 이점보들을 구할 수 있다.

 

 

-HLSL함수-

TANGENT : 정점에서 접선정보를 불어올때 사용하는 시멘틱.

BINORMAL : 정점에서 종법선정보를 불러올때 사용하는 시멘틱.

transpos() : 전치 행렬을 구하는 HLSL함수.

 

 

 

 

-실습-

 

정점 셰이더

 

struct VS_INPUT{
   float4 mPosition : POSITION;
   float3 mNormal : NORMAL;
   float2 mUV : TEXCOORD0;
   float3 mTangent: TANGENT;
   float3 mBinormal:BINORMAL;
};

//탄젠트와 바이노멀 시멘틱 구조체 선언

 

 

 

struct VS_OUTPUT{
   float4 mPosition : POSITION;
   float2 mUV: TEXCOORD0;
   float3 mLightDir : TEXCOORD1;
   float3 mViewDir: TEXCOORD2;
   float3 T : TEXCOORD3;
   float3 B : TEXCOORD4;
   float3 N : TEXCOORD5;
};

 

 

float4x4 gWorldMatrix;
float4x4 gWorldViewProjectionMatrix;

float4 gWorldLightPosition;
float4 gWorldCameraPosition;


VS_OUTPUT vs_main (VS_INPUT Input){
   VS_OUTPUT Output;
  
   Output.mPosition = mul(Input.mPosition, gWorldMatrix);
   Output.mUV = Input.mUV;
  
   float4 worldPosition = mul(Input.mPosition, gWorldViewProjectionMatrix);
   float3 lightDir = worldPosition.xyz - gWorldLightPosition.xyz;
   Output.mLightDir = normalize(lightDir);
  
  
  
   float3 viewDir = normalize(Output.mPosition.xyz - gWorldCameraPosition.xyz);
   Output.mViewDir = viewDir;
  
   
   
   float3 worldNormal = mul(Input.mNormal,(float3x3)gWorldMatrix);
   Output.N = normalize(worldNormal);
   //노멀 눨드 구하기


   float3 worldTangent = mul(Input.mNormal, (float3x3)gWorldMatrix);
   Output.T = normalize(worldTangent);
    //탄젠트 월드 구하기  


   float3 worldBinormal = mul(Input.mBinormal, (float3x3)gWorldMatrix);
   Output.B = normalize(worldBinormal);
   //바이노멀 월드 구하기


   return Output;
}

 

 

 

픽셀 셰이더

 

sampler2D DiffuseSampler;
sampler2D SpecularSampler;
sampler2D NormalSampler;

//노멀텍스쳐 샘플러

float3 gLightColor;

엠비언트 컬러

 

 

struct PS_INPUT{
   float2 mUV : TEXCOORD0;
   float3 mLightDIr : TEXCOORD1;
   float3 mViewDir : TEXCOORD2;
   float3 T : TEXCOORD3;
   float3 B : TEXCOORD4;
   float3 N : TEXCOORD5;
};

 

float4 ps_main(PS_INPUT Input):COLOR{

   float3 tangentNormal = tex2D( NormalSampler, Input.mUV).xyz;
   tangentNormal = normalize(tangentNormal * 2 - 1);
//탄젠트노멀을 0~1까지로 바꿔주는 수식  


   float3x3 TBN = float3x3(normalize(Input.T), normalize(Input.B),normalize(Input.N));
   TBN = transpose(TBN);
//전치 행열  


   float3 worldNormal = mul(TBN, tangentNormal);
  
   float3 lightDir = normalize(Input.mLightDIr);
   float3 diffuse = saturate(dot(worldNormal, -lightDir));
  
   float4 albedo = tex2D(DiffuseSampler, Input.mUV);
   diffuse = gLightColor * albedo.rgb * diffuse;
  
   float3 specular = 0;
      if(diffuse.x>0){
         float3 reflection = reflect(lightDir, worldNormal);
         float3 viewDir = normalize(Input.mViewDir);
        
         specular = saturate(dot(reflection, -viewDir));
         specular = pow(specular, 20.0f);
        
         float4 specularIntendity = tex2D(SpecularSampler, Input.mUV);
         specular *= specularIntendity.rgb * gLightColor;
      }
  
   float3 ambient = float3(0.1f,0.1f,0.1f) * albedo;
  
   return float4(ambient + diffuse * specular,1);

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by 프리랜서 디자이너

-만화 같은 명암을 입히는 툰 셰이더-

 

 

희안하게 주석 넣으면 오류난다....혹 이거 보시는 분들은 랜더몽키에 주석 빼시길....

 

 

 

정점 셰이더


struct VS_INPUT{
   float4 mPosition : POSITION;
   float3 mNormal : NORMAL;
};

struct VS_OUTPUT{
   float4 mPosition : POSITION;
   float3 mDiffuse : TEXCOORD1;
};


float4x4 gWorldViewProjectionMatrix;
//뷰,월드,프로젝션을 미리 구해 합쳐놓은 변수.
float4x4 gInvWorldMatrix;
//라이트 구하기 위한 역행열 변수.
float4 gWorldLightPosition;
//라이트 포지션.


VS_OUTPUT vs_main(VS_INPUT Input){

   VS_OUTPUT Output;
  
   Output.mPosition = mul(Input.mPosition, gWorldViewProjectionMatrix);
   //미리 구해놓은 행열을 가지고 포지션을 구한다.


   float3 objectLightPosition = mul(gWorldLightPosition,gInvWorldMatrix);

//라이트 포지션과 역행열을 이용해 라이트 포지션 구하기.


   float3 LightDir = normalize(Input.mPosition.xyz - objectLightPosition);
//   버텍스 포지션과 라이트 포지션으로 라이트 구현하기.


   Output.mDiffuse = dot(-LightDir, normalize(Input.mNormal));
//구현한 라이트와 노멀을 닷 공식으로 디퓨즈 구현.   
   return (Output);
}

 

 

 

 

픽셸셰이더

 

float3 gSurfaceColor;

//엠비언트 컬러쯤으로 보면된다....

 

struct PS_INPUT{
   float3 mDiffuse : TEXCOORD1;
};

 

float4 ps_main(PS_INPUT Input):COLOR{
   float3 diffuse = saturate(Input.mDiffuse);

//세튜레이트로 1를 넘는값은자른다.
   diffuse = ceil(diffuse * 5)/5.0f;
   //디퓨즈*5/5.0 한 값을 무조건 오림 함수로
   return float4(gSurfaceColor * diffuse.xyz,1);

//엠비언트 컬러에 디퓨즈를 곱해 반환.
}

 

**HLSL함수**

ceil():무조건 올림 함수

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by 프리랜서 디자이너

물체에 색을 입히는 디퓨즈/스페큘러맵핑

 

뭐야 왜 주석넣으면 에러나는거지??

지난 기본라이팅 파일을 복사해 이름만 바꿔서 필요한 부분만 추가해서 하고있다......

 

 

 

 

 

정점 셰이더

 

struct VS_INPUT{
   float4 mPosition : POSITION;
   float3 mNormal : NORMAL;
   float2 mUV : TEXCOORD0;
};

//Diffuse 를 위해 UV TEXCOORD0 를 추가해준다.

 

 

 

struct VS_OUTPUT{
   float4 mPosition : POSITION;
   float2 mUV: TEXCOORD0;
   float3 mDiffuse : TEXCOORD1;
   float3 mViewDir : TEXCOORD2;
   float3 mReflection : TEXCOORD3;
};

//Diffuse 를 위해 UV TEXCOORD0 를 추가해준다.

 

float4x4 gWorldMatrix;
float4x4 gViewMatrix;
float4x4 gProjectionMatrix;

float4 gWorldLightingPosition;
float4 gWorldCameraPosition;


VS_OUTPUT vs_main (VS_INPUT Input){
   VS_OUTPUT Output;
  
   Output.mPosition = mul(Input.mPosition, gWorldMatrix);
  
   float3 lightDir = Output.mPosition.xyz - gWorldLightingPosition;
   //월드노멀에 라이팅 구하기
   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;
   //OutPut에 uv를 전달해 준다.


   return Output;
}

 

 

 

 

 

픽셀 셰이더

 

sampler2D DiffuseSampler;
sampler2D SpecularSampler;

float3 gLightColor;

//텍스쳐 참조 추가, 라이트 컬러 추가

 

struct PS_INPUT{
   float2 mUV : TEXCOORD0;
   float3 mDiffuse : TEXCOORD1;
   float3 mViewDir : TEXCOORD2;
   float3 mReflection : TEXCOORD3;
};

//uv TEXCOORD 받기

 

float4 ps_main(PS_INPUT Input):COLOR{

   float4 albedo = tex2D( DiffuseSampler, Input.mUV );
   float3 diffuse = gLightColor*albedo.rgb*saturate(Input.mDiffuse);
   //tex2D함수 디퓨즈 텍스쳐 적용

  //diffuse에 텍스쳐와 라이트 컬러 적용


   float3 reflection = normalize(Input.mReflection);
   float3 viewDir = normalize(Input.mViewDir);
   float3 spacular = 0;
  
   if( diffuse.x > 0){
      spacular = saturate(dot(reflection,-viewDir));
      spacular = pow(spacular, 20.0f);
     
      float4 specularIntensity = tex2D( SpecularSampler, Input.mUV);
      spacular *= specularIntensity.rgb * gLightColor;

  //tex2D 함수로 스펙큘러 텍스쳐추가및 라이트컬러 적용
   }
   //diffuse.x값이 0보다 크면  스펙큘러 구현.
  
   float3 ambient = float3(0.1f, 0.1f, 0.1f) * albedo;

  //엠비언트에 알베도 적용

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

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by 프리랜서 디자이너

기본적인 조명 셰이더

 

 

정점셰이더

 

struct VS_INPUT{
   float4 mPosition : POSITION;
   float3 mNormal : NORMAL;
};

 

 

struct VS_OUTPUT{
   float4 mPosition : POSITION;
   float3 mDiffuse : TEXCOORD1;
   float3 mViewDir : TEXCOORD2;
   float3 mReflection : TEXCOORD3;
};

 

 

float4x4 gWorldMatrix;
float4x4 gViewMatrix;
float4x4 gProjectionMatrix;

float4 gWorldLightingPosition;
float4 gWorldCameraPosition;

 


VS_OUTPUT vs_main (VS_INPUT Input){
   VS_OUTPUT Output;
  
   Output.mPosition = mul(Input.mPosition, gWorldMatrix);
  
   float3 lightDir = Output.mPosition.xyz - gWorldLightingPosition;
   //월드노멀에 라이팅 구하기
   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);
  
   return Output;
}

 

 

픽셀 셰이더

 

struct PS_INPUT{
   float3 mDiffuse : TEXCOORD1;
   float3 mViewDir : TEXCOORD2;
   float3 mReflection : TEXCOORD3;
};

 

float4 ps_main(PS_INPUT Input):COLOR{
   float3 diffuse = saturate(Input.mDiffuse);
  
   float3 reflection = normalize(Input.mReflection);
   float3 viewDir = normalize(Input.mViewDir);
   float3 spacular = 0;
  
   if( diffuse.x > 0){
      spacular = saturate(dot(reflection,-viewDir));
      spacular = pow(spacular, 20.0f);
   }
   //diffuse.x값이 0보다 크면  스펙큘러 구현.
  
   float3 ambient = float3(0.1f, 0.1f, 0.1f);

//엠비언트추가

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

 

 

 

 

**HLSL함수**

normalize() :정규화 함수

saturate() : 0~1을 넘는 값을 잘라 냄

reflect() : 벡터반사 함수

pow() : 거듭제곱 함수

dot() : 내적 함수

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by 프리랜서 디자이너

텍스쳐 맵핑

(기본에작업된 크드를 재활용하자.... 왜냐면 귀찮으니깐....쩝....)

 

 

 

 

1. 정점 셰이더

 

struct VS_INPUT{
   float4 mPosition : POSITION;
   float2 mTexCoord : TEXCOORD0;

//인풋 구조체에 uv 추가
};

 

struct VS_OUTPUT{
   float4 mPosition : POSITION;
   float2 mTexCoord : TEXCOORD0;

//아웃풋 구조채에 uv추가
};

 

 

float4x4 gWorldMatrix;
float4x4 gViewMatrix;
float4x4 gProjectionMatrix;

 

 

VS_OUTPUT vs_main(VS_INPUT Input){
   VS_OUTPUT Output;
   Output.mPosition = mul( Input.mPosition, gWorldMatrix );
   Output.mPosition = mul( Output.mPosition, gViewMatrix );
   Output.mPosition = mul( Output.mPosition, gProjectionMatrix );
  
   Output.mTexCoord = Input.mTexCoord;
   //인풋uv받아서 아웃풋에 전달한다.
   return Output;
}

 

 

 

 

2. 픽셀 셰이더

 


sampler2D DiffuseSampler;

//2D 텍스쳐 선언

 

struct PS_INPUT{
   float2 mTexCoord : TEXCOORD;
};

//정점셰이더의 uv 인풋

 

float4 ps_main(PS_INPUT Input) : COLOR{
   float4 albedo = tex2D(DiffuseSampler, Input.mTexCoord);

//albedo라는 변수에 tex2D함수로 텍스쳐와 uv를 담는다.


   return albedo.rgba;

//albedo의rgba속성을 출력한다.
}

 

 

 

**팁**

HLSL내장 함수

tex2D(DiffuseSampler, Input.mTexCoord);

함수이름(텍스쳐, Input.uv);

이 함수로 쉽게 구현할수있다.

 

 

 

 

 

 

 

다음은 기본적인 조명 셰이더.....복습이라 조금 지겹지만 좋다..이걸로 더 제대로 셰이더를 알게 될테니...

 

 

 

 

Posted by 프리랜서 디자이너

셰이더 프로그래밍 입문-1

 

오늘부터 짬짬히 hlsl 셰이더 공부를 시작한다. 이미 예전에 포프님의 블로그를 통해 일부 공부했었지만.. 책이 나왔으니 다시 제대로 공부해보장.....물론 내 나름의 정리이니까 이포스팅을 보는 다른분들은 도움이 안될거임..ㅎㅎ;;

"같이 공부하실분은 책을 사거나 블로그로 가보세요~"

교재는 "셰이더 프로그램밍 입문"........

 

 

 

1. 공부 준비하기

별다른 준비는 필요업고 걍 AMD사의 랜더몽키를 설치하면된다.....

 

 

 

 

 

2.진짜 쉬운 빨강 셰이더

 

 

1)정점셰이더 코드

 

struct VS_INPUT{
   float4 mPosition : POSITION;
};

//구조체에는 ; 붙는다

 

struct VS_OUTPUT{
   float4 mPosition : POSITION;
};

//구조체에는 ; 붙는다

 

float4x4 gWorldMatrix;

//월드행열
float4x4 gViewMatrix;

//뷰 행열
float4x4 gProjectionMatrix;

//투영행열

 

VS_OUTPUT vs_main(VS_INPUT Input){
  
   VS_OUTPUT Output;
  
   Output.mPosition = mul( Input.mPosition, gWorldMatrix );

//정점의 월드공간 연산
   Output.mPosition = mul( Output.mPosition, gViewMatrix );

//월드 공간을 뷰공간으로 연산
   Output.mPosition = mul( Output.mPosition, gProjectionMatrix );

//뷰 공간을 투영공간으로 연산
   
   return Output;
}

 

 

**팁**

정점 셰이더 함수의 의미

VS_OUTPUT vs_main(VS_INPUT Input)

함수의 이름은 vs_main 이다.

함수의 인수는 VS_INPUT 데이터형의 input 이다.

함수의 반환값은 VS_OUTPUT 데이터형이다.

 

 

2)픽셀셰이더 코드

 

float4 ps_main() : COLOR{
   return float4 (1.0f,0.0f,0.0f,1.0f);
}

//반한되는 r,g,b,a의 값

 

 

**팁**

픽셀셰이더 함수의 의미

float4 ps_main() : COLOR

함수의이름은 ps_main 이다.

매계변수를 받지 않는다.

반환형은 float4 이다.

반환값을 백 버퍼의 컬러값으로 처리한다.

.

.

.

.

.

.

 

 

 

올만에 다시하니 오타가 또 나오네...예전에 처음 할때보다는 99% 좋아지긴 했지만 짱난다.....

다음은 텍스쳐 맵핑....

 

 

Posted by 프리랜서 디자이너