- 25: Environment Mapping
- Vector Notation
- Reflection
- Cube Maps
- Refraction
- Different indices of refraction
- EnvMap ( per vertex ) -- setup
- EnvMap ( per vertex ) -- structures
- EnvMap ( per vertex ) -- Vertex Program
- EnvMap ( per vertex ) -- Fragment Program
- Fresnel effect
- EnvMap ( per Pixel ) -- structures
- EnvMap ( per Pixel ) -- Vertex Program
- EnvMap ( per Pixel ) -- Fragment Program
- If you want an accurate simulation of those kind of effects ( e.g. reflection ) you need to go to something like ray tracing.
-
what's a little bit confusing is that in this lecture, we're mostly going to want to be reflecting the eye vector.
- N needs to be normalized
- R has same length as L
- R = L - 2N(N·L)
- fortunately there is a command built into most shading languages
- R = reflect( L,N )
- The way we're going to fake reflection effects is using a cube map.
- The reflection that we're seeing depends on the eye position.
- to lookup a cube map:
texCUBE( (samplerCUBE) envMap, (float3)vec )
- the 2nd parameter
vec
doesn't need to be normalized.
- in addition to reflection effects, we can also use cube maps for refraction effects, where we're imagining that the object is translucent and we're seeing light waves from things on the other side but they're distorted a bit because those light waves are being bent as they're going through the surface.
- T = refract( I, N, etaRatio )
- etaRatio = η₁ / η₂
- η₁ , η₂ is the index of refraction
- Vacuum: 1.0
- Air: 1.0003
- Water: 1.333
- Glass: 1.5 (ordinary window glass)
- Plastic: 1.5
- Diamond: 2.417
- Data from "The Cg Tutorial", p.184
_Cube ("Reflection Cubemap", CUBE )
= "white" {}- for this shader, I created a
_crossfade
slider that lets you crossfade between a pure reflection effect and a pure refraction effect.
samplerCUBE _Cube;
float _etaRatio;
float _crossfade;
struct a2v { // application to vertex
float4 positionOS: POSITION;
float3 normalOS: NORMAL;
};
struct v2f { // vertex 2 fragment
float4 sv: SV_POSITION;
float3 reflectWS: TEXCOORD0;
float3 refractWS: TEXCOORD1;
};
- we're going to compute the incident light vector that's pointing from where the camera is to the vertex
// incident is opposite the dir of eyedir in other programs float3 incidentWS = normalize( positionWS - _WorldSpaceCameraPos ).xyz;
- and then we use the
reflect
andrefract
command to find the reflected and refracted vectoroutput.reflectWS = reflect( incidentWS, normalWS ) ; output.refractWS = refract( incidentWS, normalWS, _etaRatio );
texCUBE
don't care about whether the 2nd parameter is unit vector, it cares about only the direction.lerp(reflectColor, refractColor, _corrsfade)
- linearly interpolate between those 2 colors it looks up depending on
_crossfade
- linearly interpolate between those 2 colors it looks up depending on
- per-vertex shader creates some problems with some clearly visible artifacts.
before we look at the per pixel code, I want to talk about an effect that I added to the per-pixel code.
-
from "The Cg Tutorial" p.189
-
Fresnel effect
- Some light reflects and some refracts
- Think about looking into water
- At shallow angles, a lot of reflection and little refraction
- Looking straight in, a lot of refraction and a little reflection
- Empirical approximation: I = -E
- remember that the incident vector for whatever historical reason is defined as being opposite of our usual Eye vector. So I is pointing from the camera to the surface instead of the other way around.
- reflectCoeff = max( 0, min( 1, bias+scale(1 + I·n )power ) )
- Cfinal = reflectCoeff x Creflected + ( 1-reflectCeoff)Crefracted
- comments
- bias, scale, power are parameters you can use to adjust this effect.
- you get a reflect coefficient in [0,1] that you use to interpolate between the reflected and refracted colors ( Creflected & Crefracted ) .
-
- 3 new properties: _fresnelBias , _fresnelScal, _fresnelPower
Toggle
- will actually create a little checkmark box that will be filled with either 0 or 1, 0 means unchecked.
- this is what I'm going to use to select a certain diagnostic mode that ignores all the cube lookups and just replaces them with a color blue and yellow.
- this will give us a way to visualize the Fresnel reflect coefficient calculation.
KeywordEnum
- drop-down menu
- let us switch between using the original crossfade I already used in the per-vertex shader and the fancier Fersnel effect.
- the way that you actually use the
Toggle
andKeywordEnum
is by placing some#pragma
into your shader code#pragma shader_feature BLUE_YELLOW #pragma multi_compile _BLEND_CROSSFADE _BLEND_FRESNEL
- "_BLEND" + "_" + upcase( "Crossfade" )
samplerCUBE _Cube;
float _etaRatio;
float _crossfade;
float _fresnelBias ; // new
float _fresnelScale ; // new
float _fresnelPower ; // new
struct a2v { // application to vertex
float4 positionOS: POSITION;
float3 normalOS: NORMAL;
};
struct v2f { // vertex 2 fragment
float4 sv: SV_POSITION;
float3 positionWS: TEXCOORD0; // changed
float3 normalWS: TEXCOORD1; // changed
};