将法线贴图添加到使用混合贴图的地形

时间:2016-08-11 20:37:29

标签: java opengl glsl lwjgl terrain

我正在尝试在我的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);
}

0 个答案:

没有答案