chap8_2 Fresnel in OGRE

Fresnel效应就是折射与反射的结合,当入射光与平面法向量重合时,反射占主要地位,当视角与平面角度接近180充时,折射占主要地位.具体的原理在DX实现时里面讲解.

/*------------------------------------------------------------
	main.cpp -- fresnel in OGRE
						(c) Seamanj.2013/8/18
------------------------------------------------------------*/
//phase1 : Add Framework
//phase2 : Add environment
//phase3 : Add water
//phase4 : add props

#define phase1 1
#define phase2 1
#define phase3 1
#define phase4 1

#if phase1
#include "ExampleApplication.h"
#include <windows.h>
#if phase2
#include "SdkCameraMan.h"
#endif
#if phase4
#include "SdkTrays.h"
#endif
class MyApplication : public ExampleApplication
#if phase3
	, public RenderTargetListener
#endif
{
#if phase3
	RenderTarget* mRefractionTarget;
	RenderTarget* mReflectionTarget;
	Plane mWaterPlane;
	Entity* mWater;
	std::vector<Entity*> mSurfaceEnts;
	std::vector<Entity*> mSubmergedEnts;
#endif

public:
	MyApplication()
	{

	}
	~MyApplication()
	{

	}
#if phase3
	 void preRenderTargetUpdate(const RenderTargetEvent& evt)
    {
        mWater->setVisible(false);  // hide the water

        if (evt.source == mReflectionTarget)  // for reflection, turn on camera reflection and hide submerged entities
		{
			mCamera->enableReflection(mWaterPlane);
			for (std::vector<Entity*>::iterator i = mSubmergedEnts.begin(); i != mSubmergedEnts.end(); i++)
				(*i)->setVisible(false);
		}
		else  // for refraction, hide surface entities
		{
			for (std::vector<Entity*>::iterator i = mSurfaceEnts.begin(); i != mSurfaceEnts.end(); i++)
				(*i)->setVisible(false);
		}
    }

    void postRenderTargetUpdate(const RenderTargetEvent& evt)
    {
        mWater->setVisible(true);  // unhide the water

        if (evt.source == mReflectionTarget)  // for reflection, turn off camera reflection and unhide submerged entities
		{
			mCamera->disableReflection();
			for (std::vector<Entity*>::iterator i = mSubmergedEnts.begin(); i != mSubmergedEnts.end(); i++)
				(*i)->setVisible(true);
		}
		else  // for refraction, unhide surface entities
		{
			for (std::vector<Entity*>::iterator i = mSurfaceEnts.begin(); i != mSurfaceEnts.end(); i++)
				(*i)->setVisible(true);
		}
    }
#endif
protected:
	void createScene()
	{
#if phase2
		mCamera->setPosition(-50, 125, 760);
		

		mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
		mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
		// create light
		Light* l = mSceneMgr->createLight();
		l->setType(Light::LT_DIRECTIONAL);
		l->setDirection(Vector3::NEGATIVE_UNIT_Y);
#if phase3
		// create our reflection & refraction render textures, and setup their render targets
		for (unsigned int i = 0; i < 2; i++)
		{
			TexturePtr tex = TextureManager::getSingleton().createManual(i == 0 ? "refraction" : "reflection",
				ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, 512, 512, 0, PF_R8G8B8, TU_RENDERTARGET);

			RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
			rtt->addViewport(mCamera)->setOverlaysEnabled(false);
			rtt->addListener(this);

			if (i == 0) mRefractionTarget = rtt;
			else mReflectionTarget = rtt;
		}
		
		// create our water plane mesh
        mWaterPlane = Plane(Vector3::UNIT_Y, 0);
        MeshManager::getSingleton().createPlane("water", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
            mWaterPlane, 700, 1300, 10, 10, true, 1, 3, 5, Vector3::UNIT_Z);

		// create a water entity using our mesh, give it the shader material, and attach it to the origin
        mWater = mSceneMgr->createEntity("Water", "water");
        mWater->setMaterialName("Examples/FresnelReflectionRefraction");//知识点1
/*知识点1:Fresnel材质 
--------------------------------------------- 
来自ogre_src_v1-7-4\Samples\Media\materials\scripts\Examples-Advanced.material文件 
--------------------------------------------- 
//----------------------------
// Distortion effects
//----------------------------

vertex_program Examples/FresnelRefractReflectVP cg
{
	source Example_Fresnel.cg//知识点2
	entry_point main_vp
	profiles vs_1_1 arbvp1
}
vertex_program Examples/FresnelRefractReflectVPold cg
{
	source Example_Fresnel.cg
	entry_point main_vp_old
	profiles vs_1_1 arbvp1
}

fragment_program Examples/FresnelRefractReflectFP cg
{
	source Example_Fresnel.cg
	entry_point main_fp
	// sorry, ps_1_1 and fp20 can't do this
	profiles ps_2_0 arbfp1
}

fragment_program Examples/FresnelRefractReflectPS asm
{
	source Example_FresnelPS.asm
	// sorry, only for ps_1_4 :)
	syntax ps_1_4

}
material Examples/FresnelReflectionRefraction
{
	// ps_2_0 / arbfp1
	technique
	{
		pass 
		{
			
			vertex_program_ref Examples/FresnelRefractReflectVP
			{
				param_named_auto worldViewProjMatrix worldviewproj_matrix
				param_named_auto eyePosition camera_position_object_space
				param_named_auto timeVal time 0.05
				param_named scroll float 1  
				param_named scale float 1 
				param_named noise float 1 
				// scroll and noisePos will need updating per frame
			}
			fragment_program_ref Examples/FresnelRefractReflectFP
			{
				param_named fresnelBias float -0.1 
				param_named fresnelScale float 1.8 
				param_named fresnelPower float 8  
				param_named tintColour float4 0 0.05 0.05 1
				param_named noiseScale float 0.05 
			}
			// Noise
			texture_unit
			{
				// Perlin noise volume
				texture waves2.dds
				// min / mag filtering, no mip
				filtering linear linear none
			}
			// Reflection
			texture_unit
			{
				// Will be filled in at runtime
				texture reflection
				tex_address_mode clamp
			}
			// Refraction
			texture_unit
			{
				// Will be filled in at runtime
				texture refraction
				tex_address_mode clamp
			}
		}
		
			
	}

	// ATI 8500 +
	technique
	{
		pass
		{
			vertex_program_ref Examples/FresnelRefractReflectVPold
			{
				param_named_auto worldViewProjMatrix worldviewproj_matrix
				param_named_auto eyePosition camera_position_object_space
				param_named fresnelBias float -0.3
				param_named fresnelScale float 1.4
				param_named fresnelPower float 8
				param_named_auto timeVal time_0_1 20
				param_named scroll float 1 
				param_named scale float 4 
				param_named noise float 1
				// scroll and noisePos will need updating per frame
			}

			// for ATI RADEON 8500 - 9200
			fragment_program_ref Examples/FresnelRefractReflectPS
			{
				// distortionRange
				param_indexed 0  float 0.025  
				// tintColour
				param_indexed 1  float4 0.05 0.12 0.15 1
			}

			// Noise
			texture_unit
			{
				// Perlin noise volume
				texture perlinvolume.dds 3d
				// min / mag filtering, no mip
				filtering linear linear none
			}
			// Reflection
			texture_unit
			{
				// Will be filled in at runtime
				texture Reflection
				tex_address_mode clamp
			}
			// Refraction
			texture_unit
			{
				// Will be filled in at runtime
				texture Refraction
				tex_address_mode clamp
			}
		}
	}    
}
*/

/*知识点2:Fresnel shader 
--------------------------------------------- 
来自ogre_src_v1-7-4\Samples\Media\materials\programs\Example_Fresnel.cg文件 
--------------------------------------------- 
// Vertex program for fresnel reflections / refractions
void main_vp(
		float4 pos			: POSITION,
		float4 normal		: NORMAL,
		float2 tex			: TEXCOORD0,
		
		out float4 oPos		: POSITION,
		out float3 noiseCoord : TEXCOORD0,
		out float4 projectionCoord : TEXCOORD1,
		out float3 oEyeDir : TEXCOORD2, 
		out float3 oNormal : TEXCOORD3, 

		uniform float4x4 worldViewProjMatrix,
		uniform float3 eyePosition, // object space
		uniform float timeVal,
		uniform float scale,  // the amount to scale the noise texture by
		uniform float scroll, // the amount by which to scroll the noise
		uniform float noise  // the noise perturb as a factor of the  time
		)
{
	oPos = mul(worldViewProjMatrix, pos);
	// Projective texture coordinates, adjust for mapping
	float4x4 scalemat = float4x4(0.5,   0,   0, 0.5, 
	                               0,-0.5,   0, 0.5,
								   0,   0, 0.5, 0.5,
								   0,   0,   0,   1);
	projectionCoord = mul(scalemat, oPos);
	// Noise map coords
	noiseCoord.xy = (tex + (timeVal * scroll)) * scale;
	noiseCoord.z = noise * timeVal;

	oEyeDir = normalize(pos.xyz - eyePosition); 
	oNormal = normal.rgb; 
	
}

// Fragment program for distorting a texture using a 3D noise texture
void main_fp(
		float3 noiseCoord			: TEXCOORD0,
		float4 projectionCoord		: TEXCOORD1,
		float3 eyeDir				: TEXCOORD2,
		float3 normal				: TEXCOORD3,
		
		out float4 col		: COLOR,
		
		uniform float4 tintColour,
		uniform float noiseScale, 
		uniform float fresnelBias,
		uniform float fresnelScale,
		uniform float fresnelPower,
		uniform sampler2D noiseMap : register(s0),
		uniform sampler2D reflectMap : register(s1),
		uniform sampler2D refractMap : register(s2)
		)
{
	// Do the tex projection manually so we can distort _after_
	float2 final = projectionCoord.xy / projectionCoord.w;

	// Noise
	float3 noiseNormal = (tex2D(noiseMap, (noiseCoord.xy / 5)).rgb - 0.5).rbg * noiseScale;
	final += noiseNormal.xz;

	// Fresnel
	//normal = normalize(normal + noiseNormal.xz);
	float fresnel = fresnelBias + fresnelScale * pow(1 + dot(eyeDir, normal), fresnelPower);

	// Reflection / refraction
	float4 reflectionColour = tex2D(reflectMap, final);
	float4 refractionColour = tex2D(refractMap, final) + tintColour;

	// Final colour
	col = lerp(refractionColour, reflectionColour, fresnel);


}


// Old version to match ATI PS 1.3 implementation
void main_vp_old(
		float4 pos			: POSITION,
		float4 normal		: NORMAL,
		float2 tex			: TEXCOORD0,
		
		out float4 oPos		: POSITION,
		out float fresnel   : COLOR,
		out float3 noiseCoord : TEXCOORD0,
		out float4 projectionCoord : TEXCOORD1,

		uniform float4x4 worldViewProjMatrix,
		uniform float3 eyePosition, // object space
		uniform float fresnelBias,
		uniform float fresnelScale,
		uniform float fresnelPower,
		uniform float timeVal,
		uniform float scale,  // the amount to scale the noise texture by
		uniform float scroll, // the amount by which to scroll the noise
		uniform float noise  // the noise perturb as a factor of the  time
		)
{
	oPos = mul(worldViewProjMatrix, pos);
	// Projective texture coordinates, adjust for mapping
	float4x4 scalemat = float4x4(0.5,   0,   0, 0.5, 
	                               0,-0.5,   0, 0.5,
								   0,   0, 0.5, 0.5,
								   0,   0,   0,   1);
	projectionCoord = mul(scalemat, oPos);
	// Noise map coords
	noiseCoord.xy = (tex + (timeVal * scroll)) * scale;
	noiseCoord.z = noise * timeVal;

	// calc fresnel factor (reflection coefficient)
	float3 eyeDir = normalize(pos.xyz - eyePosition);
	fresnel = fresnelBias + fresnelScale * pow(1 + dot(eyeDir, normal), fresnelPower);
	
}
*/
        mSceneMgr->getRootSceneNode()->attachObject(mWater);
#endif

#if phase4
		Entity* ent;



	
		
        ent = mSceneMgr->createEntity("UpperBath", "RomanBathUpper.mesh" );
		mSceneMgr->getRootSceneNode()->attachObject(ent);        
        mSurfaceEnts.push_back(ent);
		

		
        ent = mSceneMgr->createEntity("Columns", "columns.mesh");
		mSceneMgr->getRootSceneNode()->attachObject(ent);        
        mSurfaceEnts.push_back(ent);
		

		
	
		ent = mSceneMgr->createEntity("Head", "ogrehead.mesh");
		ent->setMaterialName("RomanBath/OgreStone");
        mSurfaceEnts.push_back(ent);


		SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
		headNode->setPosition(-350, 55, 130);
		headNode->yaw(Degree(90));
        headNode->attachObject(ent);

	

		ent = mSceneMgr->createEntity("LowerBath", "RomanBathLower.mesh");
        mSceneMgr->getRootSceneNode()->attachObject(ent);
        mSubmergedEnts.push_back(ent);

#endif
#endif
	}
};

INT WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd )
{
	MyApplication app;
	try
	{
		app.go();
	}
	catch( Exception& e)
	{
		MessageBoxA( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
	}
	return 0;
}

#endif


运行结果:

chap8_2 Fresnel in OGRE_第1张图片

chap8_2 Fresnel in OGRE_第2张图片

chap8_2 Fresnel in OGRE_第3张图片

chap8_2 Fresnel in OGRE_第4张图片

chap8_2 Fresnel in OGRE_第5张图片



你可能感兴趣的:(chap8_2 Fresnel in OGRE)