首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenGL延迟像素化照明

OpenGL延迟像素化照明
EN

Stack Overflow用户
提问于 2018-09-20 11:01:30
回答 1查看 325关注 0票数 2

我正在开发一个用于体素游戏的3遍延迟照明系统,但是我在像素化照明和环境遮挡方面遇到了问题。

第一阶段将屏幕上每个像素的颜色、位置和法线渲染为单独的纹理。此部分工作正常:

第二个着色器计算屏幕上每个像素的环境光遮挡值,并将其渲染到纹理。此部分不能正常工作,并且是像素化的:

原始遮挡数据:

第三个着色器使用颜色、位置、法线和遮挡纹理将游戏场景渲染到屏幕上。此阶段中的照明也是像素化的:

SSAO (第二遍)片段着色器来自屏幕空间环境光遮挡的www.LearnOpenGL.com教程:

代码语言:javascript
复制
out float FragColor;

layout (binding = 0) uniform sampler2D gPosition; // World space position
layout (binding = 1) uniform sampler2D gNormal; // Normalised normal values
layout (binding = 2) uniform sampler2D texNoise;

uniform vec3 samples[64]; // 64 random precalculated vectors (-0.1 to 0.1 magnitude)
uniform mat4 projection;

float kernelSize = 64;
float radius = 1.5;

in vec2 TexCoords;

const vec2 noiseScale = vec2(1600.0/4.0, 900.0/4.0);

void main()
{
    vec4 n = texture(gNormal, TexCoords);

    // The alpha value of the normal is used to determine whether to apply SSAO to this pixel
    if (int(n.a) > 0)
    {
        vec3 normal = normalize(n.rgb);
        vec3 fragPos = texture(gPosition, TexCoords).xyz;
        vec3 randomVec = normalize(texture(texNoise, TexCoords * noiseScale).xyz);

        // Some maths. I don't understand this bit, it's from www.learnopengl.com
        vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
        vec3 bitangent = cross(normal, tangent);
        mat3 TBN = mat3(tangent, bitangent, normal);

        float occlusion = 0.0;

        // Test 64 points around the pixel
        for (int i = 0; i < kernelSize; i++)
        {
            vec3 sam = fragPos + TBN * samples[i] * radius;

            vec4 offset = projection * vec4(sam, 1.0);
            offset.xyz = (offset.xyz / offset.w) * 0.5 + 0.5;

            // If the normal's are different, increase the occlusion value
            float l = length(normal - texture(gNormal, offset.xy).rgb);
            occlusion += l * 0.3;
        }

        occlusion = 1 - (occlusion / kernelSize);
        FragColor = occlusion;
    }
}

照明和最终片段着色器:

代码语言:javascript
复制
out vec4 FragColor;

in vec2 texCoords;

layout (binding = 0) uniform sampler2D gColor; // Colour of each pixel
layout (binding = 1) uniform sampler2D gPosition; // World-space position of each pixel
layout (binding = 2) uniform sampler2D gNormal; // Normalised normal of each pixel
layout (binding = 3) uniform sampler2D gSSAO; // Red channel contains occlusion value of each pixel

// Each of these textures are 300 wide and 2 tall.
// The first row contains light positions. The second row contains light colours.

uniform sampler2D playerLightData; // Directional lights
uniform sampler2D mapLightData; // Spherical lights

uniform float worldBrightness;

// Amount of player and map lights
uniform float playerLights;
uniform float mapLights;

void main()
{
    vec4 n = texture(gNormal, texCoords);

    // BlockData: a = 4
    // ModelData: a = 2
    // SkyboxData: a = 0;

    // Don't do lighting calculations on the skybox
    if (int(n.a) > 0)
    {
        vec3 Normal = n.rgb;
        vec3 FragPos = texture(gPosition, texCoords).rgb;
        vec3 Albedo = texture(gColor, texCoords).rgb;

        vec3 lighting = Albedo * worldBrightness * texture(gSSAO, texCoords).r;

        for (int i = 0; i < playerLights; i++)
        {
            vec3 pos = texelFetch(playerLightData, ivec2(i, 0), 0).rgb;

            vec3 direction = pos - FragPos;
            float l = length(direction);

            if (l < 40)
            {
                // Direction of the light to the position
                vec3 spotDir = normalize(direction);

                // Angle of the cone of the light
                float angle = dot(spotDir, -normalize(texelFetch(playerLightData, ivec2(i, 1), 0).rgb));

                // Crop the cone
                if (angle >= 0.95)
                {
                    float fade = (angle - 0.95) * 40;
                    lighting += (40.0 - l) / 40.0 * max(dot(Normal, spotDir), 0.0) * Albedo * fade;
                }
            }
        }

        for (int i = 0; i < mapLights; i++)
        {
            // Compare this pixel's position with the light's position
            vec3 difference = texelFetch(mapLightData, ivec2(i, 0), 0).rgb - FragPos;
            float l = length(difference);

            if (l < 7.0)
            {
                lighting += (7.0 - l) / 7.0 * max(dot(Normal, normalize(difference)), 0.0) * Albedo * texelFetch(mapLightData, ivec2(i, 1), 0).rgb;
            } 
        }

        FragColor = vec4(lighting, 1.0);
    }
    else
    {
        FragColor = vec4(texture(gColor, texCoords).rgb, 1.0);
    }
}

游戏中每个积木面孔的大小是1x1 (世界空间大小)。我试着将这些面分割成更小的三角形,如下所示,但是没有太多明显的区别。

如何提高照明和SSAO数据的分辨率以减少这些像素化伪像?提前谢谢你

EN

回答 1

Stack Overflow用户

发布于 2018-09-27 14:37:45

好消息!多亏了GameDev堆栈交换的some_rand,我能够通过将我的位置缓冲区的分辨率从GL_RGBA16F升级到GL_RGBA32F来修复这个问题。

Here is his answer.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52416937

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档