OpenGL 3.3 两个 GPU 上的两个不同结果 nVidia Optimus 与阴影映射

Posted

技术标签:

【中文标题】OpenGL 3.3 两个 GPU 上的两个不同结果 nVidia Optimus 与阴影映射【英文标题】:OpenGL 3.3 Two different results on two GPUs nVidia Optimus with Shadow mapping 【发布时间】:2013-07-17 17:27:18 【问题描述】:

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

但是现在,当我修复了大部分问题时,我正苦苦挣扎着一个我无法按照我想要的方式解决的问题(可能有一些肮脏的方式,但......这不是重点)。

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

图片:

重要 - 请注意 GTX660m 上的深度图是 redToBlack 比例,而不是像 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 个点中预采样深度图,如果所有点都相同,我不会采样更多(早期保释 - 很多性能优化!),或者如果有些不同,我会全部采样并计算阴影强度在当前片段上。

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

我认为不需要更多,但如果需要,请写下来,我会发布所需的代码。

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

【问题讨论】:

我已经在另一台笔记本电脑上测试过,这次使用的是 ATI/AMD Radeon 4670,它在笔记本电脑中相当高端(现在它相当中端?)并且影子工作正常,但还有一个问题在切换绘图时也到达了深度图(但我想它可以很容易地修复......)。我认为使用一个 API 可以解决此类平台问题,但我想不会。 :// 【参考方案1】:

我在别处得到了答案。供将来参考 - 采样深度图使用红色通道(或 .x 值),如 sample.r (/sample.x),而不是像我一样的 .b (/.z)。

【讨论】:

快速问,你是如何选择与 Optimus 一起使用的 GPU 的?就我而言,如果我选择 nvidia,它仍然使用 intel 并严重崩溃。谢谢! @LennartRolland 我通过在 exe 文件上单击鼠标右键并从那里的菜单中选择 GPU 来选择它。它必须在 nVidia 控制面板中启用(我认为默认情况下)。

以上是关于OpenGL 3.3 两个 GPU 上的两个不同结果 nVidia Optimus 与阴影映射的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL,测量 GPU 上的渲染时间

我可以在 OpenGL 中使用不同的多 GPU 吗?

CUDA 代码使两个 GPU “忙”

OpenGL 图片从文件渲染到屏幕的过程

Ubuntu 12.04 下 HD Graphics 4000 上的 OpenGL 和 GLSL 3.3

在 OS X 上的 OpenGL 上下文之间共享数据(不同的版本/配置文件)