Войти
ПрограммированиеФорумГрафика

Атмосфера: вид из космоса и с поверхности (9 стр)

Страницы: 18 9 10 11 12 Следующая »
#120
2:44, 11 окт. 2010

someone
Спасибо, то что надо! Пофиксю - отпишусь


#121
3:36, 21 окт. 2010

Да, действительно баг исправлен, хотя и читерским методом - интерполяцией скаттеринга между точками под горизонтом и над. Только вот модели атмосфер других планет, посчитанные с помощью брунетоновской демки для моего движка, разъехались - у Марса теперь как будто нет поглощения в атмосфере, у Титана очень резкая линия терминатора... Похоже надо их пересчитать. Или скопипастить код, выполняющий предрассчёт. Долгий он, предрассчёт, однако...

#122
15:51, 24 ноя. 2010

Помнится, кто-то хотел сделать open-source демку красивой Земли с ландшафтом и атмосферой. Предлагаю собрать команду и заняться. ЛОД-ландшафт, атмосфера Брунетона, потом можно добавить 3D облака...

#123
18:45, 24 ноя. 2010

Я бы с удовольствием, да знаний нет. :) Но, лично мне, очень интересно узнать, что бы получилось.

#124
6:03, 31 янв. 2011

Привожу здесь пример своей адаптации шейдеров Брунетона. Будем считать, что 3 предрассчитанные текстуры уже есть, они считаюся тем кодом, что в демке Брунетона, без изменений (имеется в виду та демка, в которой исправленны артефакты у горизонта). Планета рендерится как угодно (у меня LOD квадродерево на кубе), главное, чтобы весь рельеф лежал между Radiuses.x и Radiuses.y (см. ниже) - это радиусы нижней и верхней границы атмосферы. В фрагментный шейдер из вершинного передаются текстурные координаты (xy - для текстуры цвета, zw - для текстуры нормалей), интерполированная координата вершины (просто gl_Vertex.xyz) и тангенциальный вектор к гладкой сфере (для построения матрицы преобразования мировых координат лайта). В принципе, освещение можете делать как вам удобно, главное получить правильный вектор на солнце для функций атмосферы. В gl_LightSource[0].diffuse - цвет света Солнца.

Итак, фрагментный шейдер планеты. Комментарии на русском, думаю все будет понятно. Перед ним при загрузке вставляется код шейдера atmo_common.glsl (см. следующий пост), он содержит все функции для работы атмосферы, а так же объявления некоторых нужных ей юниформов и переменных.

// сюда вставляется файл "atmo_common.glsl", см. ниже
#include "atmo_common.glsl"

uniform sampler2D DiffMap;
uniform sampler2D BumpMap;

// Юниформы
uniform vec3 LightPos;      // Позиция солнца в object-space
uniform vec3 EyePos;        // Позиция камеры в object-space
uniform vec4 SurfParams;    // vec4(specular power, specular bright, heightmap scale, exposure)

// Из вершинного шейдера передаётся:
// gl_TexCoord[0] - интерполированные текстурные координаты
// gl_TexCoord[1] - интерполированная 3D позиция фрагмента
// gl_TexCoord[2] - интерполированный тангенциальный вектор

void main()
{
    // Атмосфера работает в полярных координатах. Для этого ей нужно знать
    // радиус планеты и радиус атмосферы, т.е. два сферических слоя, между которыми
    // рисуется дымка. Весь рельеф так же должен быть между ними.
    // Эти переменные и юниформ Radiuses объявлен в atmo_common.glsl
    planRadius2 = Radiuses.x * Radiuses.x;
    mieG2  = AtmoParams2.r * AtmoParams2.r;
    atmoH2 = Radiuses.y * Radiuses.y - planRadius2;
    atmoH  = sqrt(atmoH2);

    // Получаем нормаль и тангециальный вектор к сфере планеты (не к рельефу!)
    vec3  Normal  = normalize(gl_TexCoord[1].xyz);
    vec3  Tangent = normalize(gl_TexCoord[2].xyz);

    // Матрица трансформации для лайта
    mat3x3 Rotation = transpose(mat3x3(Tangent, cross(Tangent, Normal), Normal));

    // Получаем нормаль фрагмента из карты нормалей
    vec4  bumpData = texture2D(BumpMap, gl_TexCoord[0].zw);
    vec3  normVec = 2.0 * bumpData.xyz - 1.0;

    // В альфе карты нормалей хранится высота фрагмента - это нужно для попиксельной
    // точности атмосферы, иначе она сильно выделяет треугольники
    float height = bumpData.w * SurfParams.z;

    // Считаем точную позицию фрагмента в полярных и декартовых координатах
    // 1.000001 во избежание артефактов на плоских поверхностях с нулевой высотой
    // (как например океаны)
    FragR   = (1.000001 + height) * Radiuses.w;
    FragPos = Normal * FragR;

    // Считаем позицию камеры в object space планеты
    eyeVec = FragPos - EyePos;
    eyeVecLength = length(eyeVec);
    eyeVec /= eyeVecLength;

    // Считаем параметры фрагмента и камеры для атмосферы - H (высота),
    // R (расстояние от центра планеты), Мю (косинус угла зрения)
    // Эти переменный объявлены в atmo_common.glsl
    FragH  = (FragR - Radiuses.x) / Radiuses.z;
    FragMu = dot(FragPos, eyeVec) / FragR;
    EyeR   = length(EyePos);
    EyeH   = (EyeR - Radiuses.x) / Radiuses.z;
    EyeMu  = dot(EyePos, eyeVec) / EyeR;

    // Если камера в космосе, сдвигаем её к планете до пересечения
    // с верхней границей атмосферы
    EyePosM = EyePos;
    float d = -EyeR * EyeMu - sqrt(EyeR * EyeR * (EyeMu * EyeMu - 1.0) + Radiuses.y * Radiuses.y);
    if (d > 0.0)
    {
       EyePosM += d * eyeVec;
       eyeVecLength -= d;
       EyeMu = (EyeR * EyeMu + d) / Radiuses.y;
       EyeR = Radiuses.y;
       EyeH = 1.0;
    }

    // Позиция лайта в object space
    vec3  lightVec  = normalize(LightPos - FragPos);

    // Позиция лайта в tangent space
    vec3  lightVecTS = Rotation * lightVec;

    // Параметры освещения сферы планеты
    float cosI = dot(Normal, lightVec);
    vec3  sunLight = gl_LightSource[0].diffuse.rgb;

    // Считаем поглощение света в атмосфере на пути от солнца к фрагменту,
    // это даёт покраснение освещения на закате (функция из atmo_common.glsl)
    float rr = Radiuses.x / FragR;
    float mu = -sqrt(1.0 - rr*rr);
    sunLight *= transmittanceWithShadow(FragH, cosI, mu);

    // Считаем величину освещения фрагмента с учётом его нормали
    sunLight *= clamp(dot(normVec, lightVecTS), 0.0, 1.0);

    // Считаем вклад дневного свечения неба в освещение фрагмента
    // (функция из atmo_common.glsl)
    sunLight += irradiance(FragH, cosI) * AtmoParams1.z * gl_LightSource[0].diffuse.rgb;

    // Получаем диффузный цвет и маску воды в альфе из текстуры цвета
    vec4 diffColor = texture2D(DiffMap, gl_TexCoord[0].xy);
    vec3 groundColor = diffColor.rgb * sunLight;

    // Считаем солнечный блик на воде, обрезка по альфе для
    // более резкой границы водоемов
    if (diffColor.a > 0.5)
    {
        vec3  halfVec = normalize(lightVec - eyeVec);
        float fresnel = 0.02 + 0.98 * pow(1.0 + dot(eyeVec, halfVec), 5.0);
        float specular = fresnel * pow(max(dot(halfVec, Normal), 0.0), SurfParams.x);
        groundColor += SurfParams.y * specular * sunLight;
    }

    // Считаем поглощение света в атмосфере на пути от фрагмента к камере,
    // вариант функции с аналитической аппроксимацией (функция из atmo_common.glsl)
    vec3 Attenuation = transmittanceAnalytic(EyeR, EyeMu, eyeVecLength);

    // Другой вариант функции, использующей предрассчитанную текстуру,
    // может приводить к появлению артефактов на горизонте.
    //vec3 Attenuation = transmittance(EyeH, EyeMu, FragH, FragMu);

    // Считаем атмосферный скаттеринг на пути от фрагмента к камере,
    // это даёт знаменитую бело-голубую дымку (функция из atmo_common.glsl)
    // Скаттеринг считается по формуле S = Seye - A * Sfrag, где Seye, Sfrag -
    // величина скаттеринга в точке камеры и фрагмента, вычисляется с использованием
    // предрассчитанной 3D текстуры, A = Attenuation - поглощение света на пути от
    // фрагмента к камере.
    // Здесь используется коррекция артефакта в плоскости горизонта, который
    // наблюдается при использовании толко функции inscatterGround():
    // Функция inscatterGroundFix() делает линейную интерполяцию скаттеринга
    // над и под линией горизонта. Величина отклонения - HORIZON_FIX_EPS
    vec3 Inscatter;
    float invR = Radiuses.x / EyeR;
    HorizontMu = -sqrt(1.0 - invR * invR);
    if (abs(EyeMu - HorizontMu) < HORIZON_FIX_EPS)
        Inscatter = inscatterGroundFix(lightVec, Attenuation) * gl_LightSource[0].diffuse.rgb;
    else
        Inscatter = inscatterGround(lightVec, Attenuation) * gl_LightSource[0].diffuse.rgb;

    // Считаем результирующий цвет фрагмента -
    // ослабляем на Attenuation и добавляем Inscatter
    groundColor = groundColor * Attenuation + Inscatter * AtmoParams1.y;

    // Считаем финальный цвет фрагмента
    gl_FragColor = gl_LightModel.ambient * diffColor;
    gl_FragColor.rgb += groundColor;
    gl_FragColor.a = 1.0;

    // Применяем tone mapping
    gl_FragColor.rgb = 1.0 - exp(-SurfParams.w * gl_FragColor.rgb);
}
#125
6:10, 31 янв. 2011

atmo_common.glsl

#ifdef _FRAGMENT_
//-----------------------------------------------------------------------------
// Разрешения предрассчитанных текстур

const int RES_R = 32;
const int RES_MU = 128;
const int RES_MU_S = 32;
const int RES_NU = 8;

const float pi = 3.14159265359;

const float HORIZON_FIX_EPS = 0.004;

//-----------------------------------------------------------------------------
// Юниформы

uniform sampler2D irradianceSampler;    // precomputed skylight irradiance (E table)
uniform sampler2D transmittanceSampler; // precomputed transmittance (T table)
uniform sampler3D inscatterSampler;     // precomputed inscattered light (S table)

uniform vec4 AtmoParams1;   // vec4(density, scattering bright, skylight bright, exposure)
uniform vec4 AtmoParams2;   // vec4(MieG, MieFade, HR, HM);
uniform vec3 AtmoRayleigh;  // vec3(betaR)
uniform vec3 AtmoMieExt;    // vec3(betaMExt);
uniform vec4 Radiuses;      // vec4(atmosphere bottom radius, atmosphere top radius, atmosphere height, surface radius)

// Переменные, инициализирующиеся в шейдере планеты
float atmoH;
float atmoH2;
float planRadius2;
float mieG2;

//-----------------------------------------------------------------------------
// Реализация выборки из 4D текстуры
vec4 texture4D(float r, float mu, float muS, float nu)
{
    float rho2 = r * r - planRadius2;
    float rho = sqrt(rho2);
    float rmu = r * mu;
    float delta = rmu * rmu - rho2;
    vec4  cst = (rmu < 0.0 && delta > 0.0) ? vec4(1.0, 0.0, 0.0, 0.5 - 0.5 / float(RES_MU)) : vec4(-1.0, atmoH2, atmoH, 0.5 + 0.5 / float(RES_MU));
    float uR = 0.5 / float(RES_R) + rho / atmoH * (1.0 - 1.0 / float(RES_R));
    float uMu = cst.w + (rmu * cst.x + sqrt(delta + cst.y)) / (rho + cst.z) * (0.5 - 1.0 / float(RES_MU));
    // paper formula
    float uMuS = 0.5 / float(RES_MU_S) + max((1.0 - exp(-3.0 * muS - 0.6)) / (1.0 - exp(-3.6)), 0.0) * (1.0 - 1.0 / float(RES_MU_S));
    // better formula
    // float uMuS = 0.5 / float(RES_MU_S) + (atan(max(muS, -0.1975) * tan(1.26 * 1.1)) / 1.1 + (1.0 - 0.26)) * 0.5 * (1.0 - 1.0 / float(RES_MU_S));
    float lrp = (nu + 1.0) / 2.0 * (float(RES_NU) - 1.0);
    float uNu = floor(lrp);
    lrp -= uNu;
    return  mix(texture3D(inscatterSampler, vec3((uNu + uMuS) / float(RES_NU), uMu, uR)),
                texture3D(inscatterSampler, vec3((uNu + uMuS + 1.0) / float(RES_NU), uMu, uR)), lrp);
}

//-----------------------------------------------------------------------------
// Фазовая функция Рэлея
float phaseFunctionR(float mu) 
{
    return 3.0 / (16.0 * pi) * (1.0 + mu*mu);
}

//-----------------------------------------------------------------------------
// Фазовая функция Ми
float phaseFunctionM(float mu) 
{
    return 3.0 / (8.0 * pi) * (1.0 - mieG2) * pow(1.0 + mieG2 - 2.0*AtmoParams2.r*mu, -1.5) * (1.0 + mu*mu) / (2.0 + mieG2);
}

//-----------------------------------------------------------------------------
// Приблизительное рассеяние Ми (rayMie.rgb=C*, rayMie.w=Cm,r)
vec3 getMie(vec4 rayMie) 
{
    return rayMie.xyz * rayMie.w / max(rayMie.x, 1e-4) * (AtmoRayleigh.r / AtmoRayleigh.rgb);
}

//-----------------------------------------------------------------------------
// Освещение небом
// h = (r - planRadius) / atmoHeight) - высота в атмосфере
vec3 irradiance(float h, float muS) 
{
    float uMuS = (muS + 0.2) / (1.0 + 0.2);
    return texture2D(irradianceSampler, vec2(uMuS, h)).rgb;
}

//-----------------------------------------------------------------------------
// Поглощение (прозрачность) атмосферы вдоль бесконечного луча (r, mu),
// пересечение с землей игнорируется
// mu - косинус зенитного угла
// h = (r - planRadius) / atmoHeight) - высота в атмосфере
vec3 transmittance(float h, float mu) 
{
    float uMu = atan((mu + 0.15) / (1.0 + 0.15) * tan(1.5)) / 1.5;
    return texture2D(transmittanceSampler, vec2(uMu, sqrt(h))).rgb;
}

//-----------------------------------------------------------------------------
// Поглощение (прозрачность) атмосферы вдоль бесконечного луча (r, mu),
// или ноль, если есть пересечение с землей
// mu - косинус зенитного угла
// h = (r - planRadius) / atmoHeight) - высота в атмосфере
vec3 transmittanceWithShadow(float h, float mu, float mu0) 
{
    return (mu < mu0) ? vec3(0.0) : transmittance(h, mu);
}

//-----------------------------------------------------------------------------
// Поглощение (прозрачность) атмосферы вдоль отрезка [x, x0),
// не пересекающего землю
// mu - косинус зенитного угла отрезка [x,x0) в точке x
// h = (||x|| - planRadius) / atmoHeight) - высота в атмосфере
vec3 transmittance(float h, float mu, float h0, float mu0)
{
    if (mu > 0.0)
        return transmittance(h, mu) / transmittance(h0, mu0);
    else
        return transmittance(h0, -mu0) / transmittance(h, -mu);
}

//-----------------------------------------------------------------------------
// Оптическая толщина атмосферы отрезка луча (r, mu) длиной d,
// аналитическая аппроксимация, пересечение с землей игнорируется
// mu - косинус зенитного угла
// H - экспоненциальный коэффициет плотности
float opticalDepth(float H, float r, float mu, float d)
{
    float a = sqrt((0.5/H)*r);
    vec2  a01 = a*vec2(mu, mu + d / r);
    vec2  a01s = sign(a01);
    vec2  a01sq = a01*a01;
    float x = a01s.y > a01s.x ? exp(a01sq.x) : 0.0;
    vec2  y = a01s / (2.3193*abs(a01) + sqrt(1.52*a01sq + 4.0)) * vec2(1.0, exp(-d/H*(d/(2.0*r)+mu)));
    return sqrt((6.2831*H)*r) * exp((Radiuses.x-r)/H) * (x + dot(y, vec2(1.0, -1.0)));
}

//-----------------------------------------------------------------------------
// Поглощение (прозрачность) атмосферы вдоль отрезка луча (r, mu) длиной d,
// аналитическая аппроксимация, пересечение с землей игнорируется
vec3 transmittanceAnalytic(float r, float mu, float d)
{
    return tr = exp(-AtmoRayleigh.rgb * opticalDepth(AtmoParams2.z, r, mu, d) - AtmoMieExt.rgb * opticalDepth(AtmoParams2.w, r, mu, d));
}

//-----------------------------------------------------------------------------
// Рассеяние атмосферой вдоль луча (eyeVec, mu), солнце в направлении lightVec,
// S = S[L]|x - T(x,xs)S[l]|xs
vec3 inscatter(vec3 lightVec)
{
    float  nu = dot(eyeVec, lightVec);
    float  EyeMuS = dot(EyePosM, lightVec) / EyeR;
    float  phaseR = phaseFunctionR(nu);
    float  phaseM = phaseFunctionM(nu);
    vec4   inScatter = max(texture4D(EyeR, EyeMu, EyeMuS, nu), 0.0);

    // Avoids imprecision problems in Mie scattering when sun is below horizon
    inScatter.w *= smoothstep(0.00, AtmoParams2.y, EyeMuS);

    return inScatter.rgb * phaseR + getMie(inScatter) * phaseM;
}

//-----------------------------------------------------------------------------
// Рассеяние атмосферой вдоль отрезка [x, x0), солнце в направлении lightVec,
// S = S[L]|x - T(x,xs)S[l]|xs

vec3 inscatterGround(vec3 lightVec, vec3 Attenuation)
{
    float nu = dot(eyeVec, lightVec);
    float phaseR = phaseFunctionR(nu);
    float phaseM = phaseFunctionM(nu);
    float EyeMuS  = dot(EyePosM, lightVec) / EyeR;
    float FragMuS = dot(FragPos, lightVec) / FragR;

    vec4  eyeInScatter  = texture4D(EyeR,  EyeMu,  EyeMuS,  nu);
    vec4  fragInScatter = texture4D(FragR, FragMu, FragMuS, nu);
    vec4  inScatter = max(eyeInScatter - Attenuation.rgbr * fragInScatter, 0.0);

    // Avoids imprecision problems in Mie scattering when sun is below horizon
    inScatter.a *= smoothstep(0.0, AtmoParams2.y, EyeMuS);

    return inScatter.rgb * phaseR + getMie(inScatter) * phaseM;
}

//-----------------------------------------------------------------------------
// Рассеяние атмосферой вдоль отрезка [x, x0), солнце в направлении lightVec,
// с коррекцией вблизи горизонта
// S = S[L]|x - T(x,xs)S[l]|xs

vec3 inscatterGroundFix(vec3 lightVec, vec3 Attenuation)
{
    float nu = dot(eyeVec, lightVec);
    float phaseR = phaseFunctionR(nu);
    float phaseM = phaseFunctionM(nu);
    float EyeMuS  = dot(EyePosM, lightVec) / EyeR;
    float FragMuS = dot(FragPos, lightVec) / FragR;
    vec4  eyeInScatter, fragInScatter;

    // Avoids imprecision problems near horizon by interpolating between two points above and below horizon
    float a = ((EyeMu - HorizontMu) + HORIZON_FIX_EPS) / (2.0 * HORIZON_FIX_EPS);

    EyeMu = HorizontMu - HORIZON_FIX_EPS;
    FragR = sqrt(EyeR * EyeR + eyeVecLength * eyeVecLength + 2.0 * EyeR * eyeVecLength * EyeMu);
    FragMu = (EyeR * EyeMu + eyeVecLength) / FragR;
    eyeInScatter  = texture4D(EyeR,  EyeMu,  EyeMuS,  nu);
    fragInScatter = texture4D(FragR, FragMu, FragMuS, nu);
    vec4 inScatterA = max(eyeInScatter - Attenuation.rgbr * fragInScatter, 0.0);

    EyeMu = HorizontMu + HORIZON_FIX_EPS;
    FragR = sqrt(EyeR * EyeR + eyeVecLength * eyeVecLength + 2.0 * EyeR * eyeVecLength * EyeMu);
    FragMu = (EyeR * EyeMu + eyeVecLength) / FragR;
    eyeInScatter  = texture4D(EyeR,  EyeMu,  EyeMuS,  nu);
    fragInScatter = texture4D(FragR, FragMu, FragMuS, nu);
    vec4 inScatterB = max(eyeInScatter - Attenuation.rgbr * fragInScatter, 0.0);

    vec4 inScatter = mix(inScatterA, inScatterB, a);

    // Avoids imprecision problems in Mie scattering when sun is below horizon
    inScatter.w *= smoothstep(0.0, AtmoParams2.y, EyeMuS);

    return inScatter.rgb * phaseR + getMie(inScatter) * phaseM;
}

//-----------------------------------------------------------------------------
#endif
#126
8:37, 20 мая 2011

Neptune
> Будем считать, что 3 предрассчитанные текстуры уже есть, они считаюся тем
> кодом, что в демке Брунетона, без изменений (имеется в виду та демка, в которой
> исправленны артефакты у горизонта).
Подскажи, пожалуйста, а это какая? А то я скачал с их сайта PrecomputedAtmosphericScattering2.zip, так там код предрасчёта мне греет жутко и вешает видяху:( При этом SpaceEngine без проблем и работает.

Кажется понял, если отключить генерацию 4D-map для лайтшафтов, то загружается быстро и не виснет.

#127
23:47, 20 мая 2011

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

#128
23:50, 20 мая 2011

Neptune

да, батенька, загнались вы с шейдерами :)

особенно понравилось texture4D -  я  даже догадываюсь что будет в sm6.0

#129
23:52, 20 мая 2011

Это не я, а Эрик Брунетон:) Я лишь причесал для своих нужд

#130
10:15, 21 мая 2011

Neptune
> Лайтшафты там вообще не реализованы, т.к. нету рельефа.
да, но куски кода от них торчат, в частности, 4D текстура считается, расчёты там тяжёлые и мой бедный ATI 5450 Catalist 10.6 на этом деле виснет (может быть драйвер, конечно).

Вчера вырезал, подкрутил шейдер (выключил TRANSMITTANCE_NON_LINEAR и INSCATTER_NON_LINEAR, а то с ними из космоса ерунда какая-то - почти всё белое) - вроде работает и неплохо.

> Могу кинуть свою переделанную демку, она умеет сохранять предрасчитанные
> текстуры в бинарный файл и грузить обратно (для теста).
да, если можно - погонять всё пригодится:)

ещё вопрос. Как я понял, у тебя шейдер атмосферы применяется при выводе геометрии, а в брунетоновской демке намекается скорее на применение как пост эффект (ты сам об этом где-то тут писал тоже, но я сейчас не нашёл). Сейчас как думаешь, что правильнее?

#131
12:33, 21 мая 2011

Neptune

оффтопик, забил таки на Cg ?

#132
0:16, 23 мая 2011

serpinf
> да, но куски кода от них торчат, в частности, 4D текстура считается, расчёты
> там тяжёлые
4D текстура это вообще для атмосферы. По сути, это самая главная функция. Модель зависит от 4 параметров - высота, угол луча зрения, угловая высота солнца и угол между лучом зрения и солнцем. Поэтому 4D текстура. По-идее от последнего параметра можно избавиться, усложнив вычисления, но видимо 2 выборки из 3D текстуры быстрее.

serpinf
> > Могу кинуть свою переделанную демку, она умеет сохранять предрасчитанные
> > текстуры в бинарный файл и грузить обратно (для теста).
> да, если можно - погонять всё пригодится:)
Ок, завтра закину.

serpinf
> ещё вопрос. Как я понял, у тебя шейдер атмосферы применяется при выводе
> геометрии, а в брунетоновской демке намекается скорее на применение как пост
> эффект (ты сам об этом где-то тут писал тоже, но я сейчас не нашёл). Сейчас как
> думаешь, что правильнее?
Да, у меня атмосфера применяется при выводе геометрии. Это значит что для планет с атмосферой и без используются разные шейдеры. Когда понадобится рисовать корабль, для него тоже придётся переключать шейдеры, когда он в космосе и когда в атмосфере. ИМХО если у тебя будут другие пост эффекты, лучше делай атмосферу тоже пост эффектом, не нужно будет таскать кучу шейдеров. И корректно обработается ситуация с гигантским кораблём, торчащим наполовину из атмосферы:)

innuendo
> оффтопик, забил таки на Cg ?
Забил, ибо ATI не знает, что такое Cg, а кроссплатформенность нужна... Кстати, у меня Cg шейдеры на NVidia работали ощутимо быстрее, чем сейчас аналогичные glsl. Обидно, но делать две системы шейдеров отдельно для ATI и NVidia влом:)

#133
0:21, 23 мая 2011

Neptune
> 4D текстура это вообще для атмосферы.
Правка: я тут ступил, приняв multiple scattering за что-то другое и гордо его вырезал:( Ну не получается оценить его прелесть, когда карточка от него комп вешает...

Neptune
> Да, у меня атмосфера применяется при выводе геометрии. Это значит что для
> планет с атмосферой и без используются разные шейдеры. Когда понадобится
> рисовать корабль, для него тоже придётся переключать шейдеры, когда он в
> космосе и когда в атмосфере. ИМХО если у тебя будут другие пост эффекты, лучше
> делай атмосферу тоже пост эффектом, не нужно будет таскать кучу шейдеров. И
> корректно обработается ситуация с гигантским кораблём, торчащим наполовину из
> атмосферы:)
у меня несколько другая проблема:) Приложение типа Google Earth скорее, корабли пока не нужны, а вот 3D модели зданий, деревьев, машин... всё это будет. соответственно оно будет многократно перекрываться, а шейдер атмосферы, как я понимаю, достаточно дорогой. Единственное, что смущает - как подружить атмосферу с прозрачностью. В статье говорят, что они как раз применяют атмосферу ДО блендинга, а это означает, что при рисовании геометрии...

Правка: Наверное, буду делать как в статье - сначала depth-only pass, а потом рендерить всё с атмосферой, потом поверх прозрачные.

#134
4:55, 23 мая 2011

Neptune
> Забил, ибо ATI не знает, что такое Cg

знает, с ограничениями правда :)

Neptune
> Кстати, у меня Cg шейдеры на NVidia работали ощутимо быстрее,

а это интересно, однако - что-то тут не так

Страницы: 18 9 10 11 12 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.