我正在尝试在我的lwjgl游戏中为我的地形实现法线贴图,我已经取得了很好的视觉效果,但是当我使用法线贴图时,我的游戏从~70fps下降到~40fps。
这就是为什么我想知道是否有更好的方法这样做,我目前正在使用混合贴图,它使用r,g,b和黑色来确定应在地形上绘制的纹理。这就是为什么我需要至少4个Sampler2D(每个纹理一个)和4个用于法线贴图,4个用于镜面映射等等。这给我留下了~15个Sampler2D,这可能就是为什么fps下降到如此低的水平。
是否有人对此问题有任何替代方案和/或建议?
顶点着色器:
#version 140
in vec3 position;
in vec2 textureCoords;
in vec3 normal;
out vec2 pass_textureCoords;
out vec3 surfaceNormal;
out vec3 toLightVector[4];
out vec3 toCameraVector;
out float visibility;
out vec4 shadowCoords;
uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition[4];
uniform mat4 toShadowMapSpace;
uniform float transitionDistance;
const float density = 0.007;
const float gradient = 1.5;
uniform float shadowDistance;
uniform vec4 plane;
void main(){
vec4 worldPosition = transformationMatrix * vec4(position,1.0);
shadowCoords = toShadowMapSpace * worldPosition;
gl_ClipDistance[0] = dot(worldPosition, plane);
mat4 modelViewMatrix = viewMatrix * transformationMatrix;
vec4 positionRelativeToCam = viewMatrix * worldPosition;
gl_Position = projectionMatrix * positionRelativeToCam;
pass_textureCoords = textureCoords;
surfaceNormal = (transformationMatrix * vec4(normal, 0.0)).xyz;
for(int i = 0; i<4; i++){
toLightVector[i] = lightPosition[i] - worldPosition.xyz;
}
toCameraVector = (inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0)).xyz - worldPosition.xyz;
float distance = length(positionRelativeToCam.xyz);
visibility = exp(-pow((distance*density), gradient));
visibility = clamp(visibility, 0.0, 1.0);
distance = distance - (shadowDistance - transitionDistance);
distance = distance / transitionDistance;
shadowCoords.w = clamp(1.0-distance, 0.0, 1.0);
}
片段着色器:
#version 140
in vec2 pass_textureCoords;
in vec3 surfaceNormal;
in vec3 toLightVector[4];
in vec3 toCameraVector;
in float visibility;
in vec4 shadowCoords;
out vec4 out_Color;
uniform sampler2D backgroundTexture;
uniform sampler2D rTexture;
uniform sampler2D gTexture;
uniform sampler2D bTexture;
uniform int useNormalMapping;
uniform sampler2D backgroundNormalTexture;
uniform sampler2D rNormalTexture;
uniform sampler2D gNormalTexture;
uniform sampler2D bNormalTexture;
uniform int useSpecularMapping;
uniform sampler2D backgroundSpecularTexture;
uniform sampler2D rSpecularTexture;
uniform sampler2D gSpecularTexture;
uniform sampler2D bSpecularTexture;
uniform sampler2D blendMap;
uniform sampler2D shadowMap;
uniform vec3 lightColor[4];
uniform vec3 attenuation[4];
uniform float shineDamper;
uniform float reflectivity;
uniform vec3 skyColor;
uniform float mapSize;
const int pcfCount = 1;
const float totalTexels = (pcfCount * 2.0 + 1.0) * (pcfCount * 2.0 + 1.0);
const float levels = 3;
const int useCelShading = 0;
void main(void){
float texelSize = 1.0 / mapSize;
float total = 0.0;
for(int x = -pcfCount; x <= pcfCount; x++){
for(int y = -pcfCount; y <= pcfCount; y++){
float objectNearestLight = texture(shadowMap, shadowCoords.xy + vec2(x, y) * texelSize).r;
if(shadowCoords.z > objectNearestLight){
total += 1.0;
}
}
}
total /= totalTexels;
float lightFactor = 1.0 - (total * shadowCoords.w / 2);
vec4 blendMapColor = texture(blendMap, pass_textureCoords);
float backTextureAmount = 1 - (blendMapColor.r + blendMapColor.g + blendMapColor.b);
vec2 tiledCoords = pass_textureCoords * 80.0;
//normal colors
vec4 totalNormal = vec4(surfaceNormal, 1.0);
if(useNormalMapping == 0){
totalNormal += texture(backgroundNormalTexture, tiledCoords, -1) * backTextureAmount;
totalNormal += texture(backgroundNormalTexture, tiledCoords, -1) * blendMapColor.r;
totalNormal += texture(gNormalTexture, tiledCoords, -1) * blendMapColor.g;
totalNormal += texture(bNormalTexture, tiledCoords, -1) * blendMapColor.b;
}
//specular maps
vec3 spec = vec3(0);
if(useSpecularMapping == 1){
spec += (texture(backgroundSpecularTexture, tiledCoords, -1) * backTextureAmount).rgb;
spec += (texture(rSpecularTexture, tiledCoords, -1) * blendMapColor.r).rgb;
spec += (texture(gSpecularTexture, tiledCoords, -1) * blendMapColor.g).rgb;
spec += (texture(bSpecularTexture, tiledCoords, -1) * blendMapColor.b).rgb;
}
vec4 normalMapValue = 2.0 * (totalNormal) - 1.0;
vec3 unitNormal = normalize(normalMapValue.rgb);
//specular colors
vec3 totalSpecular = vec3(0.0);
vec4 backgroundTextureColor = texture(backgroundTexture, tiledCoords) * backTextureAmount;
vec4 rTextureColor = texture(rTexture, tiledCoords) * blendMapColor.r;
vec4 gTextureColor = texture(gTexture, tiledCoords) * blendMapColor.g;
vec4 bTextureColor = texture(bTexture, tiledCoords) * blendMapColor.b;
vec4 totalColor = backgroundTextureColor + rTextureColor + gTextureColor + bTextureColor;
vec3 unitVectorToCamera = normalize(toCameraVector);
vec3 totalDiffuse = vec3(0.0);
for(int i = 0; i < 4; i ++){
float distance = length(toLightVector[i]);
float attFactor = attenuation[i].x + (attenuation[i].y * distance) + (attenuation[i].z * distance * distance);
vec3 unitLightVector = normalize(toLightVector[i]);
float nDot1 = dot(unitNormal, unitLightVector);
float brightness = max(nDot1, 0.0);
float level = floor(brightness * levels);
if(useCelShading == 1){
brightness = level / levels;
}
vec3 lightDirection = -unitLightVector;
vec3 reflectedLightDirection = reflect(lightDirection, unitNormal);
float specularFactor = dot(reflectedLightDirection, unitVectorToCamera);
specularFactor = max(specularFactor, 0.0);
float dampedFactor = pow(specularFactor, shineDamper);
level = floor(dampedFactor * levels);
if(useCelShading == 1){
dampedFactor = level / levels;
}
totalDiffuse = totalDiffuse + (brightness * lightColor[i]) / attFactor;
totalSpecular = totalSpecular + (dampedFactor * reflectivity * lightColor[i]) / attFactor;
}
totalDiffuse = max(totalDiffuse, 0.2) * lightFactor;
totalSpecular *= spec.xyz;
out_Color = vec4(totalDiffuse, 1.0) * totalColor + vec4(totalSpecular, 1.0);
out_Color = mix(vec4(skyColor, 1.0), out_Color, visibility);
}