Итак, я работаю над проектом (как для обучения, так и для создания игры в будущем) на C++, и для рендеринга я выбрал OpenGL 3.3. Я работал на Intel HD 4000, встроенном в мой процессор, так как он открывает новые приложения по умолчанию, и все прошло гладко. Но затем я попытался открыть его на своем втором графическом процессоре - nVidia GTX660m, который намного быстрее, и я ожидал от него гораздо большего FPS. Но нет, не только у меня были десятки десятков ошибок (например, у Intel все было в порядке, если я использовал vec3 в качестве цвета во фрагментном шейдере, но и у nVidia было полное безумие, если я не использовал vec4...). Конечно, никаких ошибок при компиляции, так что это очень сложно исправить...
Но теперь, когда я исправил большую часть этого, я борюсь с одной проблемой, которую я не могу исправить, как мне бы хотелось (могут быть некоторые грязные способы, но... не в этом дело).
Вкратце: я генерирую на обоих графических процессорах действительные карты глубины, но на графическом процессоре nVidia это не шкала серого, а шкала от красного к черному, что крайне странно, поскольку один и тот же код на той же машине (почти ) должен работать одинаково (также тот же API!). Из-за этого мой фрагментный шейдер, вероятно, не догоняет его, а на nVidia не определяет освещенные области и полностью темные (по крайней мере, в прожекторах направленный свет не работает).
Pics:
ВАЖНО. Обратите внимание, что карты глубины на 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 (которая намного мощнее) - это очень странно. Хотя я думаю, что это потому, что я не рисую высокополигональные, а только очень низкополигональные. Я прав?