OpenGL 3.3 两个 GPU 上具有阴影贴图的 nVidia Optimus 上的两种不同结果

标签 opengl nvidia optimus shadow-mapping

所以我正在用 C++ 开发一个项目(以便将来学习和创建游戏),并且为了渲染我选择了 OpenGL 3.3。我一直在使用我的处理器中内置的 Intel HD 4000,因为它会打开默认的新应用程序,一切都很顺利。但后来我尝试在我的第二个 GPU - nVidia GTX660m 上打开它,它的速度要快得多,而且我预计它的 FPS 会更高。但不,不仅我有几十个错误(例如 - 如果我在片段着色器中使用 vec3 作为颜色,Intel 就可以正常工作,但如果我没有使用 vec4,nVidia 就会变得完全疯狂......)。当然,编译时没有任何错误,因此很难修复...

但是现在,当我解决了大部分问题时,我正在努力解决一个我无法按照我的意愿解决的问题(可能有一些肮脏的方法,但是......这不是重点)。

简而言之:我在两个 GPU 上生成有效的深度图,但在 nVidia GPU 上它不是灰度图,而是红到黑比例 这非常奇怪,因为相同的代码在相同的代码上机器(几乎)应该运行相同的(也相同的 API!)。由于这个事实,我的片段着色器可能无法 catch 它,并且在 nVidia 上无法检测到照明区域并且其完全黑暗(至少在聚光灯下,定向光不起作用)。

图片: Image when using Intel HD4000 (which comes from my i5 ivy-bridge cpu) Image when using nVidia GTX660m when running app from RMB menu. No soft shadows for "buildings" (big blocks) nor the flashlight effect (spot light)

重要 - 请注意 GTX660m 上的深度图是红到黑比例,而不是像 Intel GPU 上的灰度图。顶部一张来自定向光,底部一张当然来自点光源。

我的片段着色器: #版本330核心

in vec2 UV;                         //Coords for standard texture (model)
in vec4 ShadowCoord;                //Coords for directional light (pos)
in vec4 POVShadowCoord;             //Coords for spot light (flashlight) (pos)

out vec4 color;                     //Output color

uniform sampler2D myTextureSampler; //Standard texture with data for models
uniform sampler2D shadowMap;        //Shadowmap for directional light
uniform sampler2D POVshadowMap;     //Shadowmap for spot light (flashlight)

void main(){
    vec3 tex_data = texture2D( myTextureSampler, UV ).rgb;

    float bias = 0.005;
    float visibility = 0.7;
    float decrease = 0.002;

    int early_bailing = 0;
    if ( texture2D( shadowMap, ShadowCoord.xy + vec2(0,0)/1850.0 ).z  <  ShadowCoord.z-bias ) {
        visibility -= decrease; early_bailing++;
    }
    if ( texture2D( shadowMap, ShadowCoord.xy + vec2(-2,-2)/1850.0 ).z  <  ShadowCoord.z-bias ) {
        visibility -= decrease; early_bailing++;
    }
    if ( texture2D( shadowMap, ShadowCoord.xy + vec2(-2, 2)/1850.0 ).z  <  ShadowCoord.z-bias ) {
        visibility -= decrease; early_bailing++;
    }
    if ( texture2D( shadowMap, ShadowCoord.xy + vec2( 2,-2)/1850.0 ).z  <  ShadowCoord.z-bias ) {
        visibility -= decrease; early_bailing++;
    }
    if ( texture2D( shadowMap, ShadowCoord.xy + vec2( 2, 2)/1850.0 ).z  <  ShadowCoord.z-bias ) {
        visibility -= decrease; early_bailing++;
    }
    if(early_bailing < 5) {
        if(early_bailing > 0) {
            for (int i=-2; i < 2; i++) {
                for(int j = -2; j < 2; j++) {
                    if(i ==  0 && j ==  0) continue;
                    if(i == -2 && j == -2) continue;
                    if ( texture2D( shadowMap, ShadowCoord.xy + vec2(i,j)/850.0 ).z  <  ShadowCoord.z-bias )
                        visibility -= decrease;
                }
            }
        }
    } else {
        visibility -= 14 * decrease;
    }

    float x = POVShadowCoord.x/POVShadowCoord.w;
    float y = POVShadowCoord.y/POVShadowCoord.w;
    bias = 0.0004;
    if(x < 0 || x > 1 || y < 0 || y > 1) {
        visibility -= 0.6;
    } else {
        float min_visibility = visibility - 0.6;
        if ( textureProj( POVshadowMap, POVShadowCoord.xyw).z < (POVShadowCoord.z - bias)/POVShadowCoord.w) {
            visibility = min_visibility;
        } else {
            //Flashlight effect
            float dx = 0.5 - x;
            float dy = 0.5 - y;
            visibility -= sqrt(dx*dx + dy*dy);
            if(visibility < min_visibility)
                visibility = min_visibility;
        }
    }

    color = vec4(visibility * tex_data, 1);
}

第一部分是定向光 - 我在 5 个点中预采样深度图,如果所有点都相同,我不会采样更多(早期放弃 - 大量性能优化!),或者如果有些不同,我会采样所有点并计算阴影强度在当前片段上。

第二部分只是点光源深度图的样本,然后我检查距光线中心的距离以模拟手电筒效果(中心更强)。

我认为不需要更多内容,但如果需要,请写信,我将发布所需的代码。

另外 - 阴影贴图只有 16 位精度 (GL_DEPTH_COMPONENT16) Intel HD4000 比我的 GTX660m 更快(它更强大) - 这很奇怪。虽然我认为这是因为我没有画任何高多边形,只是画了许多非常低多边形。我说得对吗?

最佳答案

我在其他地方得到了答案。供将来引用 - 采样深度图使用红色 channel (或 .x 值),如sample.r (/sample.x),而不是像我那样使用 .b (/.z)。

关于OpenGL 3.3 两个 GPU 上具有阴影贴图的 nVidia Optimus 上的两种不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17728947/

相关文章:

c++ - 在 Optimus 笔记本电脑中以编程方式强制使用 NVIDIA GPU

OpenGL 精湛的第 5 版。三角形.cpp

c++ - 为什么片段着色器比渲染纹理更快?

java - OpenGL 翻译键输入

tensorflow - 在 WSL2 上安装 Tensorflow-GPU

ubuntu - 我需要哪个 nvidia 驱动程序版本?

c++ - 尝试使用 glDrawArraysInstanced() 时 OpenGL 崩溃

c - Vulkan SDK 一次仅检测 1 个 GPU

c++ - 使用 GLAD 时无法命名变量 "far"和 "near"