球面貼圖用於環境反射(reflection), 紋理座標的生成與cube map的reflection mode類似:
推導如下:
頂點處理器:
// Sphere Mapping Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130
// Incoming per vertex... position and normal
in vec4 vVertex;
in vec3 vNormal;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
// Color to fragment program
smooth out vec2 vVaryingTexCoord;
// Generates a sphere map texture coordinate based on the eyespace surface normal
// and the eye space vertex.
vec2 sphereMap(in vec3 normal, in vec3 ecPosition3)
{
float m;
vec3 r, u;
u = normalize(ecPosition3);
r = reflect(u, normal);
m = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z + 1.0) * (r.z + 1.0));
return vec2 (r.x / m + 0.5, r.y / m + 0.5);
}
void main(void)
{
// Normal in Eye Space
vec3 vEyeNormal = normalMatrix * vNormal;
// Vertex position in Eye Space
vec4 vVert4 = mvMatrix * vVertex;
vec3 vEyeVertex = vVert4.xyz / vVert4.w;
// Pass on the texture coordinates
vVaryingTexCoord = sphereMap(vEyeNormal, vEyeVertex);
// Don't forget to transform the geometry!
gl_Position = mvpMatrix * vVertex;
}
片斷着色器:
// ADS Point lighting Shader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130
out vec4 vFragColor;
uniform sampler2D sphereMap;
smooth in vec2 vVaryingTexCoord;
void main(void)
{
vFragColor = texture(sphereMap, vVaryingTexCoord);
}
用於球面貼圖的紋理圖像:
在一幅平面紋理圖像中對各個方向的顏色進行編碼就相當於把一個擦得鋥亮的完美球體放在環境的中央,然後在極遠處用長焦鏡頭對它進行拍照。需要編碼的區域就是覆蓋整個紋理圖像的一個圓形區域,它與紋理圖像的頂、底、左、右邊緣相切。這個圓形區域之外的紋理值不會對結果產生影響,因爲它們不會在環境紋理中使用。
如下圖: