Fresnel.h
bool frameRenderingQueued(const FrameEvent &evt) { // update the fish spline path animations and loop as needed mFishAnimTime += evt.timeSinceLastFrame; while (mFishAnimTime >= FISH_PATH_LENGTH) mFishAnimTime -= FISH_PATH_LENGTH; for (unsigned int i = 0; i < NUM_FISH; i++) { mFishAnimStates[i]->addTime(evt.timeSinceLastFrame * 2); // update fish swim animation // set the new position based on the spline path and set the direction based on displacement Vector3 lastPos = mFishNodes[i]->getPosition(); mFishNodes[i]->setPosition(mFishSplines[i].interpolate(mFishAnimTime / FISH_PATH_LENGTH)); mFishNodes[i]->setDirection(mFishNodes[i]->getPosition() - lastPos, Node::TS_PARENT, Vector3::NEGATIVE_UNIT_X); mFishNodes[i]->setFixedYawAxis(true); } return SdkSample::frameRenderingQueued(evt); } 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); } }
void setupWater() { // 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"); mSceneMgr->getRootSceneNode()->attachObject(mWater); }
Examples-Advanced.material
//---------------------------- // Distortion effects //---------------------------- vertex_program Examples/FresnelRefractReflectVP cg { source Example_Fresnel.cg 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 } vertex_program Examples/FresnelRefractReflectVPGLSLES glsles { source Example_FresnelVp.glsles entry_point main profiles glsles } 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 } fragment_program Examples/FresnelRefractReflectFPGLSLES glsles { source Example_FresnelFp.glsles entry_point main profiles glsles } 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 } } } // glsles technique { pass { vertex_program_ref Examples/FresnelRefractReflectVPGLSLES { 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/FresnelRefractReflectFPGLSLES { 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 } } } }
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); }
Example_FresnelFp.glsles
#version 100 precision highp float; precision highp int; precision lowp sampler2D; precision lowp samplerCube; uniform vec4 tintColour; uniform float noiseScale; uniform float fresnelBias; uniform float fresnelScale; uniform float fresnelPower; uniform sampler2D noiseMap; uniform sampler2D reflectMap; uniform sampler2D refractMap; varying vec3 noiseCoord; varying vec4 projectionCoord; varying vec3 eyeDir; varying vec3 normal; // Fragment program for distorting a texture using a 3D noise texture void main() { // Do the tex projection manually so we can distort _after_ vec2 final = projectionCoord.xy / projectionCoord.w; // Noise vec3 noiseNormal = (texture2D(noiseMap, (noiseCoord.xy / 5.0)).rgb - 0.5).rbg * noiseScale; final += noiseNormal.xz; // Fresnel //normal = normalize(normal + noiseNormal.xz); float fresnel = fresnelBias + fresnelScale * pow(1.0 + dot(eyeDir, normal), fresnelPower); // Reflection / refraction vec4 reflectionColour = texture2D(reflectMap, final); vec4 refractionColour = texture2D(refractMap, final) + tintColour; // Final colour gl_FragColor = mix(refractionColour, reflectionColour, fresnel); }
Example_FresnelVp.glsles
#version 100 precision highp float; precision highp int; precision lowp sampler2D; precision lowp samplerCube; attribute vec4 uv0; attribute vec4 vertex; uniform mat4 worldViewProjMatrix; uniform vec3 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 varying vec3 noiseCoord; varying vec4 projectionCoord; varying vec3 eyeDir; varying vec3 normal; // Vertex program for fresnel reflections / refractions void main() { gl_Position = worldViewProjMatrix * vertex; // Projective texture coordinates, adjust for mapping mat4 scalemat = mat4(0.5, 0.0, 0.0, 0.5, 0.0, -0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0); projectionCoord = scalemat * gl_Position; // Noise map coords noiseCoord.xy = (uv0.xy + (timeVal * scroll)) * scale; noiseCoord.z = noise * timeVal; eyeDir = normalize(vertex.xyz - eyePosition); }
Example_FresnelPS.asm
ps.1.4 // conversion from Cg generated ARB_fragment_program to ps.1.4 by NFZ // command line args: -profile arbfp1 -entry main_fp // program main_fp // c0 : distortionRange // c1 : tintColour // testure 0 : noiseMap // texture 1 : reflectMap // texture 2 : refractMap // v0.x : fresnel // t0.xyz : noiseCoord // t1.xyw : projectionCoord def c2, 2, 1, 0, 0 // Cg: distort.x = tex3D(noiseMap, noiseCoord).x; // arbfp1: TEX R0.x, fragment.texcoord[0], texture[0], 3D; // sample noise map using noiseCoord in TEX unit 0 texld r0, t0.xyz // get projected texture coordinates from TEX coord 1 // will be used in phase 2 texcrd r1.xy, t1_dw.xyw mov r1.z, c2.y // Cg: distort.y = tex3D(noiseMap, noiseCoord + yoffset).x; // arbfp1: ADD R1.xyz, fragment.texcoord[0], c1; // arbfp1: TEX R1.x, R1, texture[0], 3D; // arbfp1: MOV R0.y, R1.x; // Cg: distort = (distort * 2 - 1) * distortionRange; // arbfp1: MAD R0.xy, R0, c0.x, -c0.y; // arbfp1: MUL R0.xy, R0, u0.x; // (distort * 2 - 1) same as 2*(distort -.5) so use _bx2 // Cg: final = projectionCoord.xy / projectionCoord.w; // Cg: final += distort; // arbfp1: RCP R0.w, fragment.texcoord[1].w; // arbfp1: MAD R0.xy, fragment.texcoord[1], R0.w, R0; // final = (distort * projectionCoord.w) + projectionCoord.xy // for ps.1.4 have to re-arrange things a bit to perturb projected texture coordinates mad r0.xyz, r0_bx2, c0.x, r1 phase // do dependant texture reads // Cg: reflectionColour = tex2D(reflectMap, final); // arbfp1: TEX R0, R0, texture[1], 2D; // sampe reflectMap using dependant read : texunit 1 texld r1, r0.xyz // Cg: refractionColour = tex2D(refractMap, final) + tintColour; // arbfp1: TEX R1, R0, texture[2], 2D; // sample refractMap : texunit 2 texld r2, r0.xyz // adding tintColour that is in global c1 // arbfp1: ADD R1, R1, u1; add r2, r2, c1 // Cg: col = lerp(refractionColour, reflectionColour, fresnel); // arbfp1: ADD R0, R0, -R1; // arbfp1: MAD result.color, fragment.color.primary.x, R0, R1; lrp r0, v0.x, r1, r2