# 学习OpenGL ES之教你制作迷雾

### 线性计算模型

``````fogFactor = 1 - (fogEnd - distance) / (fogEnd - fogStart)
fogFactor = clamp(fogFactor, 0, 1)
``````

``````float linearFogFactor(float fogStart, float fogEnd) {
vec4 worldVertexPosition = modelMatrix * vec4(fragPosition, 1.0);
float distanceToEye = distance(eyePosition, worldVertexPosition.xyz);
// linear
float fogFactor = (fogEnd - distanceToEye) / (fogEnd - fogStart); // 1.0 ~ 0.0
fogFactor = 1.0 - clamp(fogFactor, 0.0, 1.0);  // 0.0 ~ 1.0
return fogFactor;
}
``````

``````mix(inputColor, fog.fogColor, fogFactor);
``````

### exp计算模型

exp计算模型是利用常量e来参与公式计算的一个模型。公式和曲线如下。

``````fogFactor = 1 - 1 / e^(distance * fogDensity)
fogFactor = clamp(fogFactor, 0, 1)
``````

``````float exponentialFogFactor(float fogDensity) {
vec4 worldVertexPosition = modelMatrix * vec4(fragPosition, 1.0);
float distanceToEye = distance(eyePosition, worldVertexPosition.xyz);
float fogFactor = 1.0 / exp(distanceToEye * fogDensity);
fogFactor = 1.0 - clamp(fogFactor, 0.0, 1.0);  // 0.0 ~ 1.0
return fogFactor;
}
``````

### 2次exp计算模型

``````fogFactor = 1 - 1 / e^((distance * fogDensity)^2)
fogFactor = clamp(fogFactor, 0, 1)
``````

``````float exponentialSquareFogFactor(float fogDensity) {
vec4 worldVertexPosition = modelMatrix * vec4(fragPosition, 1.0);
float distanceToEye = distance(eyePosition, worldVertexPosition.xyz);
float fogFactor = 1.0 / exp(pow(distanceToEye * fogDensity, 2.0));
fogFactor = 1.0 - clamp(fogFactor, 0.0, 1.0);  // 0.0 ~ 1.0
return fogFactor;
}
``````

``````struct Fog {
int fogType; // 0: 线性，1: exp 2: 2次exp
float fogStart;
float fogEnd;
float fogIndensity;
vec3 fogColor;
};
``````

`colorWithFog`统一处理雾的计算。

``````vec3 colorWithFog(vec3 inputColor) {
float fogFactor = 0.0;
if (fog.fogType == 0) {
fogFactor = linearFogFactor(fog.fogStart, fog.fogEnd);
} else if (fog.fogType == 1) {
fogFactor = exponentialFogFactor(fog.fogIndensity);
} else if (fog.fogType == 2) {
fogFactor = exponentialSquareFogFactor(fog.fogIndensity);
}
return mix(inputColor, fog.fogColor, fogFactor);
}
``````

### 传值给Fog

``````typedef enum : NSUInteger {
FogTypeLinear = 0,
FogTypeExp = 1,
FogTypeExpSquare  = 2,
} FogType;

typedef struct {
FogType fogType;
// for linear
GLfloat fogStart;
GLfloat fogEnd;
// for exp & exp square
GLfloat fogIndensity;
GLKVector3 fogColor;
} Fog;
``````

``````Fog fog;
fog.fogColor = GLKVector3Make(1, 1,1);
fog.fogStart = 0;
fog.fogEnd = 200;
fog.fogIndensity = 0.02;
fog.fogType = FogTypeExpSquare;
self.fog = fog;
``````

``````- (void)bindFog:(GLContext *)context {
[context setUniform1i:@"fog.fogType" value:self.fog.fogType];
[context setUniform1f:@"fog.fogStart" value:self.fog.fogStart];
[context setUniform1f:@"fog.fogEnd" value:self.fog.fogEnd];
[context setUniform1f:@"fog.fogIndensity" value:self.fog.fogIndensity];
[context setUniform3fv:@"fog.fogColor" value:self.fog.fogColor];
}
``````