OpenGL 3.3 Два разных результата на двух графических процессорах nVidia Optimus с отображением теней

Итак, я работаю над проектом (как для обучения, так и для создания игры в будущем) на C++, и для рендеринга я выбрал OpenGL 3.3. Я работал на Intel HD 4000, встроенном в мой процессор, так как он открывает новые приложения по умолчанию, и все прошло гладко. Но затем я попытался открыть его на своем втором графическом процессоре - nVidia GTX660m, который намного быстрее, и я ожидал от него гораздо большего FPS. Но нет, не только у меня были десятки десятков ошибок (например, у Intel все было в порядке, если я использовал vec3 в качестве цвета во фрагментном шейдере, но и у nVidia было полное безумие, если я не использовал vec4...). Конечно, никаких ошибок при компиляции, так что это очень сложно исправить...

Но теперь, когда я исправил большую часть этого, я борюсь с одной проблемой, которую я не могу исправить, как мне бы хотелось (могут быть некоторые грязные способы, но... не в этом дело).

Вкратце: я генерирую на обоих графических процессорах действительные карты глубины, но на графическом процессоре nVidia это не шкала серого, а шкала от красного к черному, что крайне странно, поскольку один и тот же код на той же машине (почти ) должен работать одинаково (также тот же API!). Из-за этого мой фрагментный шейдер, вероятно, не догоняет его, а на nVidia не определяет освещенные области и полностью темные (по крайней мере, в прожекторах направленный свет не работает).

Pics: Изображение при использовании Intel HD4000 (из моего процессора i5 ivy-bridge)Изображение при использовании nVidia GTX660m при запуске приложения из меню ПКМ. Нет мягких теней для зданий (большие блоки) и эффекта фонарика (прожектор)

ВАЖНО. Обратите внимание, что карты глубины на GTX660m имеют шкалу от красного до черного, а не шкалу серого, как на графическом процессоре Intel. Верхняя карта — от направленного света, а нижняя — от точечного света.

Мой FragmentShader: ядро ​​версии 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 (которая намного мощнее) - это очень странно. Хотя я думаю, что это потому, что я не рисую высокополигональные, а только очень низкополигональные. Я прав?


person RippeR    schedule 18.07.2013    source источник
comment
Я протестировал его на другом ноутбуке, на этот раз с ATI/AMD Radeon 4670, который был скорее Hi-End для ноутбуков (теперь скорее Mid-end?), и тени работали нормально, хотя возникла другая проблема при переключении отрисовки карт глубины. (но я думаю, что это можно довольно легко исправить...). Я думал, что использование одного API решит такие проблемы с платформой, но, похоже, нет. :/   -  person RippeR    schedule 18.07.2013


Ответы (1)


У меня есть ответ в другом месте. Для справки в будущем - карта глубины выборки использует красный канал (или значение .x), например, sample.r (/sample.x), а не .b (/ .z), как у меня.

person RippeR    schedule 19.07.2013
comment
Быстрый вопрос, как вы выбрали графический процессор для использования с Optimus? В моем случае, если я выбираю nvidia, он все еще использует Intel и ужасно падает. Спасибо! - person Lennart Rolland; 18.11.2016
comment
@LennartRolland Я выбрал его, щелкнув правой кнопкой мыши исполняемый файл и выбрав GPU в меню. Это должно быть включено в панели управления nVidia (я думаю, по умолчанию). - person RippeR; 16.04.2017