1. 쉐이더 코드 작성(GrayScale.cg)

sampler RT : register(s0);

void calculateMaterialColorInDirectionalLight(	float4 position			: POSITION,
								float4 normal			: NORMAL,
								float2 uv				: TEXCOORD0,
						  
								out float4 oPosition	: POSITION,
								out float3 oNormal		: COLOR,
								out float2 oUv			: TEXCOORD0,

								uniform float4x4	worldViewProj,
								uniform float4x4	world,
								uniform float3		ambient,
								uniform float		diffusePower,
								uniform float3		diffuse,
								uniform float3		lightDirection, 
								uniform float3		lightColor
								)
{
	oPosition = mul(worldViewProj, position);
	oUv = uv;
	oNormal = (normalize(mul(world, normal))).xyz;
	oNormal = diffuse * diffusePower * saturate(dot(oNormal, normalize(lightDirection)));
	oNormal = lightColor * (ambient + oNormal);
}

void calculateGrayScaleInMaterialColor(	float3 normal			: COLOR,
							float2 uv				: TEXCOORD0,
										
							out float4 oColor		: COLOR,
										
							uniform sampler2D	RT : register(s0),
							uniform float		grayRatio
							)
{
	float3 tex_col = tex2D(RT, uv).rgb * normal;
	float3 greyscale = tex_col * (1 - grayRatio) + dot(tex_col, float3(0.3, 0.59, 0.11)) * grayRatio;
	oColor = float4(greyscale, 1.0);
}

 - 출력 변수에는 out으로 선언한다.
 - C 코드에서 입력할 데이터들은 uniform으로 선언한다.

2. 메터리얼 작성(GrayScale.material)

vertex_program ColorConvertor/GrayScale_vp cg
{
	source GrayScale.cg
	entry_point calculateMaterialColorInDirectionalLight
	profiles vs_1_1 arbvp1

	default_params
	{
		param_named_auto worldViewProj worldviewproj_matrix
		param_named_auto world world_matrix

		param_named ambient float3 0.2 0.2 0.2
		param_named diffusePower float 1.5
		param_named diffuse float3 0.8 0.8 0.8
		param_named lightDirection float3 0.0 2.0 2.0
		param_named lightColor float3 1.0 1.0 1.0
	}
}

fragment_program ColorConvertor/GrayScale_fp cg
{
	source GrayScale.cg
	entry_point calculateGrayScaleInMaterialColor
	profiles ps_2_0 fp30

	default_params
	{
		param_named grayRatio float 0.0
	}
}

material ColorConvertor/GrayScale
{
	technique
	{
		pass
		{
			vertex_program_ref ColorConvertor/GrayScale_vp
			{
			
			}
			// alternate shadow caster program
			fragment_program_ref ColorConvertor/GrayScale_fp
			{
			}

			texture_unit RT
			{
				texture nskingr.jpg 2d
			}
		}
	}
}

 - vertex_program은 버텍스 쉐이더
 - fragment_program은 픽셀 쉐이더

 - source는 쉐이더 코드 파일명
 - entry_point는 쉐이더 코드 함수명
 - profiles는 컴파일할 쉐이더 버전

 - param_named_auto는 3번째 값(위에서 worldviewproj_matrix, world_matrix)에 따라 ogre에서 매 프레임마다 알아서 갱신시켜주는 데이터
 - param_named는 C 코드에서 설정을 해주어야 하는 데이터

 - texture_unit은 텍스쳐 설정(위에서는 RT라는 이름으로 텍스쳐 설정, 쉐이더 코드의 RT에 매칭)

 - 이름에 '/'가 들어간 것은 계층구조의 의미가 아님. 그냥 통채로 이름이다.

 - 픽셀 쉐이더는 오히려 1.1 지원이 안되는 카드가 있음(여기 참고).

3. 엔터티에 메터리얼 설정

    Entity* head2 = mSceneMgr->createEntity("Head2", "ninja.mesh");
    MaterialPtr material = (Ogre::MaterialPtr)Ogre::MaterialManager::getSingleton().getByName ("ColorConvertor/GrayScale");
    head2->setMaterial(material);
    Ogre::GpuProgramParametersSharedPtr filterParams = material->getTechnique(0)->getPass(0)->getVertexProgramParameters();
    filterParams->setNamedConstant("ambient", Vector3(0.2f, 0.2f, 0.2f));
    filterParams->setNamedConstant("diffusePower", 1.5f);
    filterParams->setNamedConstant("diffuse", Vector3(0.8f, 0.8f, 0.8f));
    filterParams->setNamedConstant("lightDirection", Vector3(0.0f, 2.0f, 2.0f));
    filterParams->setNamedConstant("lightColor", Vector3(1.0f, 1.0f, 1.0f));
    Ogre::GpuProgramParametersSharedPtr filterParams2 = material->getTechnique(0)->getPass(0)->getFragmentProgramParameters();
    filterParams2->setNamedConstant("grayRatio", 0.0f);
- 쉐이더와 메터리얼 파일 경로를 resources_d.cfg에 포함시켜야 한다.
- 메터리얼에서 기본값을 설정해 놓았으면 코드에서 설정할 필요는 없다.
- 메터리얼의 상수값을 각 엔터티에 다르게 설정하고 싶으면 Ogre::Material::clone("새로운 메터리얼 이름") 함수를 사용해서 메터리얼을 복사해서 사용하면 된다. 복사된 메터리얼은 원본 메터리얼의 상수 설정값을 그대로 가지고 있다.
블로그 이미지

영스파파

3D 세상을 만들기 위한 프로그래밍 정보들을 정리하는 공간

,