SSAO 文物分为三部分

2023-12-07

我真的很难解决 SSAO 着色器的问题,并且迫切需要一些帮助。基本上,着色器似乎对某些对象有效,但在其他对象上看起来很糟糕。从下面您可以看到球体看起来是正确的,但立方体似乎在法线上进行了不应该的遮挡。这是一个屏幕截图:

Notice edges of cube

我的着色器基于本教程:http://devmaster.net/posts/3095/shader-effects-screen-space-ambient-occlusion

在我的渲染链中,我渲染了 2 个渲染目标,这些目标将在稍后的一些后期处理效果中使用。其中之一存储位置和深度。另一个存储法线。两个目标都是浮动纹理。

这是每个步骤的屏幕截图。

Normals, Depth, Position

这是我的位置/深度着色器:

顶点着色器:

varying vec4 vPosition;
.....
vPosition = mvPosition;

碎片着色器:

uniform float linearDepth; //Cam far - cam near
varying vec4 vPosition;
...
float ld = length(vPosition) / linearDepth;
gl_FragColor = vec4(vPosition.x, vPosition.y, vPosition.z, ld);

这是普通的着色器:

顶点着色器:

varying vec3 vNormal;
...
vec3 transformedNormal = normalMatrix * objectNormal;
vNormal = transformedNormal;

片段着色器:

gl_FragColor = vec4( normalize( vNormal ).xyz, 1.0);

这是我的 SSAO 片段着色器:

uniform sampler2D tDiffuse;    // The original scene texture
uniform sampler2D tPositions;    // View space position data
uniform sampler2D tNormals;    // View space normal vectors
uniform sampler2D tNoise;    // Normalmap to randomize the sampling kernel
uniform vec2 texelSize;

/// Occluder bias to minimize self-occlusion.
uniform float occluderBias;

/// Specifies the size of the sampling radius.
uniform float samplingRadius;

uniform float onlyAO;

/// <summary>
/// Ambient occlusion attenuation values.
/// These parameters control the amount of AO calculated based on distance
/// to the occluders. You need to play with them to find the right balance.
///
/// .x = constant attenuation. This is useful for removing self occlusion. When
///         set to zero or a low value, you will start to notice edges or wireframes
///         being shown. Typically use a value between 1.0 and 3.0.
///
///    .y = linear attenuation. This provides a linear distance falloff.
/// .z = quadratic attenuation. Smoother falloff, but is not used in this shader.
/// <summary>
uniform vec2 attenuation;


/// <summary>
/// Varying variables.
/// <summary>
varying vec2 vUv;

/// <summary>
/// Sample the ambient occlusion at the following UV coordinate.
/// <summary>
/// <param name=srcPosition>3D position of the source pixel being tested.</param>
/// <param name=srcNormal>Normal of the source pixel being tested.</param>
/// <param name=uv>UV coordinate to sample/test for ambient occlusion.</param>
/// <returns>Ambient occlusion amount.</returns>
float SamplePixels (vec3 srcPosition, vec3 srcNormal, vec2 uv)
{
    // Get the 3D position of the destination pixel
    vec3 dstPosition = texture2D(tPositions, uv).xyz;

    // Calculate ambient occlusion amount between these two points
    // It is simular to diffuse lighting. Objects directly above the fragment cast
    // the hardest shadow and objects closer to the horizon have minimal effect.
    vec3 positionVec = dstPosition - srcPosition;
    float intensity = max(dot(normalize(positionVec), srcNormal) - occluderBias, 0.0);

    // Attenuate the occlusion, similar to how you attenuate a light source.
    // The further the distance between points, the less effect AO has on the fragment.
    float dist = length(positionVec);
    float attenuation = 1.0 / (attenuation.x + (attenuation.y * dist));

    return intensity * attenuation;
}


/// <summary>
/// Fragment shader entry.
/// <summary>
void main ()
{
    // Get position and normal vector for this fragment
    vec3 srcPosition = texture2D(tPositions, vUv).xyz;
    vec3 srcNormal = texture2D(tNormals, vUv).xyz;
    vec2 randVec = normalize(texture2D(tNoise, vUv).xy * 2.0 - 1.0);
    float srcDepth = texture2D(tPositions, vUv).w;

    // The following variable specifies how many pixels we skip over after each
    // iteration in the ambient occlusion loop. We can't sample every pixel within
    // the sphere of influence because that's too slow. We only need to sample
    // some random pixels nearby to apprxomate the solution.
    //
    // Pixels far off in the distance will not sample as many pixels as those close up.
    float kernelRadius = samplingRadius * (1.0 - srcDepth);

    // Sample neighbouring pixels
    vec2 kernel[4];
    kernel[0] = vec2(0.0, 1.0);        // top
    kernel[1] = vec2(1.0, 0.0);        // right
    kernel[2] = vec2(0.0, -1.0);    // bottom
    kernel[3] = vec2(-1.0, 0.0);    // left

    const float Sin45 = 0.707107;    // 45 degrees = sin(PI / 4)

    // Sample from 16 pixels, which should be enough to appromixate a result. You can
    // sample from more pixels, but it comes at the cost of performance.
    float occlusion = 0.0;
    for (int i = 0; i < 4; ++i)
    {
        vec2 k1 = reflect(kernel[i], randVec);
        vec2 k2 = vec2(k1.x * Sin45 - k1.y * Sin45,
                       k1.x * Sin45 + k1.y * Sin45);
        k1 *= texelSize;
        k2 *= texelSize;

        occlusion += SamplePixels(srcPosition, srcNormal, vUv + k1 * kernelRadius);
        occlusion += SamplePixels(srcPosition, srcNormal, vUv + k2 * kernelRadius * 0.75);
        occlusion += SamplePixels(srcPosition, srcNormal, vUv + k1 * kernelRadius * 0.5);
        occlusion += SamplePixels(srcPosition, srcNormal, vUv + k2 * kernelRadius * 0.25);
    }

    // Average and clamp ambient occlusion
    occlusion /= 16.0;
    occlusion = clamp(occlusion, 0.0, 1.0);

// Blend the two 
vec3 colour =  texture2D(tDiffuse, vUv).xyz;
//colour = clamp(colour - occlusion, 0.0, 1.0);

occlusion = 1.0 - occlusion;

//gl_FragColor.xyz = pow(colour, vec3(1.0 / 2.2));
if ( onlyAO == 1.0 )
    gl_FragColor.xyz = vec3( occlusion, occlusion, occlusion );
else if ( onlyAO == 2.0 )
    gl_FragColor.xyz = vec3( srcNormal.x, srcNormal.y, srcNormal.z );
else if ( onlyAO == 3.0 )
    gl_FragColor.xyz = vec3( srcDepth, srcDepth, srcDepth );
else
{
    //// Blend the two 
    //colour = clamp(colour - occlusion, 0.0, 1.0); 

    //// Apply gamma correction 
    //gl_FragColor.xyz = pow(colour, vec3(1.0 / 2.2)); 
    //gl_FragColor.w = 1.0;

    gl_FragColor.xyz = colour * occlusion;
}

gl_FragColor.w = 1.0;

}

看起来法线并不垂直于立方体的表面,这可能是来自shading材料的参数。

尝试设置THREE.FlatShading参数为shading材料的选项。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SSAO 文物分为三部分 的相关文章

  • 访问被拒绝查找属性 ro.vendor.hwui.texture_cache_size

    在启动活动时我收到此错误 Access denied finding property ro vendor hwui texture cache size 在 Android OREO 之前一切都工作正常 但在 Android Pie 中却
  • 调试 Three.js 中的低 FPS

    我正在处理 Three js WebGL 场景 当我缩小时 我注意到 60 FPS 以便所有观察结果 约 20 000 个三角形 都在视图中 但当我放大时 FPS 非常低 因此只有一个小三角形的子集在视野中 我想弄清楚是什么导致了这种差异
  • 在 Three.js 中将贝塞尔曲线转换为平面道路

    我试图根据之前计算得到的一些贝塞尔曲线在 Three js 中绘制一条弯曲的道路 问题是我找不到转换曲线序列的方法 一条从上一条曲线的末尾开始 到一个曲面 我有一个 3D 场景 其中有一些汽车 一条用飞机创建的道路 并且绘制了即将到来的道路
  • 从 GraphicBuffer 读取时出现意外的像素数据布局

    我目前正在本机 Android 框架中的一个平台上工作 在该平台上我使用 GraphicBuffer 来分配内存 然后从中创建 EGLImage 然后将其用作 OpenGL 中的纹理 使用简单的全屏四边形 问题是 当我从 GraphicBu
  • 在 Libgdx 中实现简单运动模糊的意外结果

    在所附的两张图片中 libgdx 的桌面屏幕截图按预期运行 不幸的是 我的 Galaxy Nexus 的屏幕截图与预期不符 我正在尝试创建一个简单的运动模糊或轨迹效果 Rendering as I expected on my deskto
  • 如何使用 OpenGL ES 2.0 旋转对象?

    在 OpenGL ES 1 1 中 您可以使用glRotatef 旋转模型 但 OpenGL ES 2 0 中不存在该函数 那么 在OpenGL ES 2 0中如何进行旋转呢 为了遵循克里斯蒂安所说的 您需要自己跟踪模型视图矩阵并操纵它来执
  • 使用 glDrawElements 时在 OpenGL 核心配置文件中选取三角形

    我正在使用 glDrawElements 绘制三角形网格 并且希望能够使用鼠标单击来拾取 选择三角形 三角形的网格可以很大 在固定功能 OpenGL 中 可以使用 GL SELECT http content gpwiki org inde
  • 即使在顶点着色器中使用,glGetUniformLocation()也会返回-1

    我正在尝试用法线渲染一个简单的立方体 我使用以下代码来初始化着色器 void initShader const char vertexShaderPath const char fragmentShaderPath cout lt lt I
  • 在 TypeScript 中使用三个 Js + OrbitControl

    我无法得到this http www example com 在 TypeScript 中使用上述组合的示例 I have and 在我的html中和打字稿文件
  • Three.js 对象的“中心”是什么?

    当我使用 Blender 对对象进行建模时 我能够明确定义其发生平移和旋转的中心位置 当使用 Three js 对象时 我似乎没有找到等效的对象 Three js 对象是否具有定义其 中心 位置的属性 如果不是 物体的中心是如何确定的 在
  • Three.js - 将 WebGL 和 CSS3D 与 iFrame 混合

    我准备了一个混合的工作页面WebGL and CSS3D 在SO的一点帮助下here https stackoverflow com questions 24681170 three js properly blending css3d a
  • 具有漫反射和法线贴图纹理的 3D 模型

    我想使用 libgdx 的资源加载器加载具有漫反射纹理和法线贴图的 3D 模型 据我所知 fbx 以及转换后的 g3dj g3db 格式可以包含漫反射纹理 正如我在 fbx conv 示例中看到的那样 骑士 g3db 如何为其添加法线贴图纹
  • Three.js 椭圆

    如何在 Three js 中创建一个椭圆 我看过这个 在 THREE js 中绘制椭圆 https stackoverflow com questions 11419896 drawing an ellipse in three js 但如
  • 使用 OpenGL 着色器进行数学计算 (C++)

    我有一个矩阵 例如 100x100 尺寸 我需要对每个元素进行计算 matrix i j tt 8 5例如 我有一个巨大的矩阵 我想使用 OpenGL 着色器来实现该算法 我想使用着色器 例如 uniform float val unifo
  • libgdx SpriteBatch 渲染到纹理

    是否可以使用 libGdx 适用于 Android 桌面的 Java 引擎 中的 SpriteBatch 渲染到纹理 如果是这样 怎么办 基本上我想将所有内容渲染到 512 x 256 纹理的 320 x 240 区域 然后缩放区域以适合屏
  • 如何将任意颜色的色度键滤镜应用到实时摄像头源ios?

    基本上我想将色度键滤镜应用到 ios 实时摄像头源 但我希望用户选择将被另一种颜色替换的颜色 我找到了一些使用绿屏的示例 但我不知道如何动态替换颜色而不仅仅是绿色 知道如何以最佳性能实现这一目标吗 您之前曾询问过我的情况GPUImage h
  • OpenGL ES 2.0 中的纹理点?

    我正在尝试在 OpenGL ES 2 0 中为粒子系统实现纹理点 例如点精灵 我遇到的问题是所有点都渲染为实心黑色方块 而不是正确映射纹理 我已经验证 gl PointCoord 实际上返回从 0 0 到 1 0 的 x y 值 这将映射到
  • 为什么拥有单独的投影矩阵但结合模型和视图矩阵会有好处?

    当您学习 3D 编程时 您会被告知用 3 个变换矩阵来思考是最简单的 模型矩阵 该矩阵对于每个模型都是独立的 它根据需要旋转和缩放对象 最后将其移动到 3D 世界中的最终位置 模型矩阵将模型坐标转换为世界坐标 视图矩阵 对于大量对象 如果不
  • 将自己的结构传递到 opengl es 2.0 着色器中

    我想尝试 OpenGL ES 2 0 编程指南 一书中的照明示例 在着色器中他们制作了两种结构 struct directional light vec3 direction normalized light direction in ey
  • OpenGL ES 片段着色器显然不可能返回白色

    这是一个奇怪的现象 我有一个片段着色器 据我所知只能返回黑色或红色 但它将像素渲染为白色 如果我删除一根特定的线 它会返回我期望的颜色 它适用于 WebGL 但不适用于 Raspberry Pi 上的 OpenGL ES 这是着色器代码 如

随机推荐