Странно работает шейдер атмосферы

Использую шейдер О'Нила для реализации атмосферы планет. Всё работает отлично, пока планеты находятся на позиции glm::vec3(0, 0, 0), но если их сдвигать, то что-то работает во фрагментном шейдере неверно...Вот код шейдеров и скриншоты:

Вершинный шейдер:
#version 460 core
layout (location = 0) in vec3 aPos;

out vec3 fPosition;
out mat3 modelMat3;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform float zCoef; // for log z-buffer (2.0 / log2(farPlane + 1.0)) [логарифмический z-буффер]

void main() {
    fPosition = aPos;
    modelMat3 = mat3(model);
    gl_Position = projection * view * model * vec4(aPos, 1);
    /// Log z-buffer [логарифмический z-буффер]
    gl_Position.z = log2(max(1e-6, gl_Position.w + 1.0)) * zCoef - 1.0;
    gl_Position.z *= gl_Position.w;
}
Фрагментный шейдер:
#version 460 core

in vec3 fPosition;
in mat3 modelMat3;

uniform vec3 camPosition;
uniform vec3 lightPos;
uniform vec3 C_R; // Atmosphere color [цвет атмосферы]
uniform float innerRadius;
uniform float outerRadius;

const float PI = 3.14159265359;
const float MAX = 10000.;
const float E = 12.3;
const float K_R = 0.0639999;
const float K_M = 0.0031;
const float G_M = -0.717998;

const int numOutScatter = 10;
const float fNumOutScatter = 10.0;
const int numInScatter = 4;
const float fNumInScatter = 4.0;

float SCALE_H = 6.0 / (outerRadius - innerRadius);
float SCALE_L = 1.0 / (outerRadius - innerRadius);

vec3 rayDirection(vec3 camPosition) {
    vec3 ray = modelMat3 * fPosition - camPosition;
    float far = length(ray);
    return ray /= far;
}

vec2 rayIntersection(vec3 p, vec3 dir, float radius) {
    float b = dot(p, dir);
    float c = dot(p, p) - radius * radius;

    float d = b * b - c;
    if (d < 0.0) {
        return vec2(MAX, -MAX);
    }
    d = sqrt( d );

    float near = -b - d;
    float far = -b + d;

    return vec2(near, far);
}

// Mie
// g : ( -0.75, -0.999 )
//      3 * ( 1 - g^2 )               1 + c^2
// F = ----------------- * -------------------------------
//      2 * ( 2 + g^2 )     ( 1 + g^2 - 2 * g * c )^(3/2)
float miePhase(float g, float c, float cc) {
    float gg = g * g;

    float a = (1.0 - gg) * (1.0 + cc);

    float b = 1.0 + gg - 2.0 * g * c;
    b *= sqrt(b);
    b *= 2.0 + gg;

    return 1.5 * a / b;
}

float rayleighPhase(float cc) {
    return 0.75 * (1.0 + cc);
}

float density(vec3 p) {
    return exp(-(length(p) - innerRadius) * SCALE_H);
}

float optic(vec3 p, vec3 q) {
    vec3 step = (q - p) / fNumOutScatter;
    vec3 v = p + step * 0.5;

    float sum = 0.0;
    for(int i = 0; i < numOutScatter; i++) {
        sum += density(v);
        v += step;
    }
    sum *= length(step)*SCALE_L;
    return sum;
}

vec3 colorInScatter(vec3 o, vec3 dir, vec2 e, vec3 l) {
    float len = (e.y - e.x) / fNumInScatter;
    vec3 step = dir * len;
    vec3 p = o + dir * e.x;
    vec3 v = p + dir * (len * 0.5);

    vec3 sum = vec3(0.0);
    for(int i = 0; i < numInScatter; i++) {
        vec2 f = rayIntersection(v, l, outerRadius);
        vec3 u = v + l * f.y;
        float n = (optic(p, v) + optic(v, u))*(PI * 4.0);
        sum += density(v)* exp(-n * (K_R * C_R + K_M));
        v += step;
    }
    sum *= len * SCALE_L;
    float c = dot(dir, -l);
    float cc = c * c;
    return sum * (K_R * C_R * rayleighPhase(cc) + K_M * miePhase(G_M, c, cc)) * E;
}

void main() {
    vec3 dir = rayDirection(camPosition);
    vec3 eye = camPosition;
    vec3 l = normalize(lightPos);

    vec2 e = rayIntersection(eye, dir, outerRadius);
    if (e.x > e.y) {
        discard;
    }
    vec2 f = rayIntersection(eye, dir, innerRadius);
    e.y = min(e.y, f.x);

    vec3 I = colorInScatter(eye, dir, e, l);

    gl_FragColor = vec4(I, 1.0);
}

С Венерой всё в порядке, она на позиции (0 0 0), а Земля нет, и вот что происходит..Никак не могу понять, почему так

введите сюда описание изображения введите сюда описание изображения

Всё, пофикшено, решение написал в ответе на вопрос Кому нужно, берите шейдер, он намного легче исходного шейдера О'Нила в применении и понимании параметров, которые нужно передавать) введите сюда описание изображения введите сюда описание изображения


Ответы (1 шт):

Автор решения: Глеб Труфанов

Решено!! Хз, как додумался.. В общем перед рендером атмосферы для планеты нужно в шейдере ставить положение камеры как раз-таки относительно этой планеты, то есть вот так

_mainAtmosphereShader->SetVec3("camPosition", _camera.GetPosition() - _earth->GetPosition());
_earthAtmosphere->SetShader(shader);
_earthAtmosphere->AdjustToParent();
_earthAtmosphere->Draw();

_mainAtmosphereShader->SetVec3("camPosition", _camera.GetPosition() - _venus->GetPosition());
_venusAtmosphere->SetShader(shader);
_venusAtmosphere->AdjustToParent();
_venusAtmosphere->Draw();
→ Ссылка