GLSL大气散射不随变换缩放 [英] GLSL Atmospheric Scattering Not Scaling With Transformations

查看:91
本文介绍了GLSL大气散射不随变换缩放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在GLSL 4.10版中实现大气散射.我正在从此Shadertoy着色器中修改着色器 https://www.shadertoy.com/view/lslXDr .我程序中的气氛是从行星球体的缩放版本创建的.

I am trying to implement atmospheric scatting in GLSL version 4.10. I am adapting the shaders from the this Shadertoy shader https://www.shadertoy.com/view/lslXDr. The atmosphere in my program is created from a scaled version of the planet sphere.

我使用了实际的散射方程,但是对于大多数相机位置,大气的内半径与球的外径并不对齐.我知道这是因为大气层的半径大于行星球体的半径,但我似乎无法使其按比例缩放.

I have the actual scattering equations working, but the inner radius of the atmosphere does not line up with the outer radius of the sphere for most camera positions. I know this is from the radius of the atmosphere being bigger than the planet sphere, but I cannot seem to get it to scale right.

我的问题在这里得到最好的说明.这些图片放大了模型.可以看出,大气的内半径与行星的半径(深蓝色球体)不匹配.

My problem is best illustrated here. The model is scaled up in these pictures. As can be seen, the atmosphere inner radius does not match the radius of the planet (the dark blue sphere).

在此模型被缩放和转换.大气层偏离相机中心,内部大气层仍未与行星对齐.

Here the model is scaled and translated. The atmosphere is off center from the camera and the inner atmosphere is still not lined up with the planet.

这里是顶点着色器,本质上是通过着色器的传递

Here is the vertex shader, which is essentially a pass through shader

#version 410

in vec4 vPosition;
in vec3 vNormal;

out vec3 fPosition;
out mat3 m;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{   
    fPosition = vec3(vPosition);
    m = mat3(model);

    gl_Position = projection*view*model*vPosition;
}

还有片段着色器.

#version 410

uniform float time;
uniform vec3 camPosition;
uniform float fInnerRadius;
uniform float fOuterRadius;

in vec3 fPosition;
in mat3 m;

out vec4 FragColor;

const float PI = 3.14159265359;
const float degToRad = PI / 180.0;
const float MAX = 10000.0;

float K_R = 0.166;
const float K_M = 0.0025;
const float E = 14.3;
const vec3 C_R = vec3(0.3, 0.7, 1.0);
const float G_M = -0.85;

float SCALE_H = 4.0 / (fOuterRadius - fInnerRadius);
float SCALE_L = 1.0 / (fOuterRadius - fInnerRadius);

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

vec3 rayDirection(vec3 camPosition) {
    vec3 ray = m*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;
}

// Reyleigh
// g : 0
// F = 3/4 * ( 1 + c^2 )
float rayleighPhase( float cc ) {
    return 0.75 * ( 1.0 + cc );
}


float density(vec3 p) {
    return exp(-(length(p) - fInnerRadius) * 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 inScatter(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, fOuterRadius);
        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 (void)
{
    vec3 dir = rayDirection(vec3(camPosition.x, 0.0, camPosition.z));
    vec3 eye = vec3(camPosition.x, 0.0, camPosition.z);

    vec3 l = normalize(vec3(0.0, 0.0, 1.0));

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

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

    FragColor = vec4(I, 1.0);
}

如果需要的话,这里是绘制气氛的代码.在scaleFactor之外,绘制行星的代码具有基本相同的转换.

If needed here is the code that draws the atmosphere. The code that draws the planet has essentially the same transformations sans the scaleFactor.

void drawAtmosphere()
{
    glUseProgram(atmosphereShader);

    v = getViewMatrix();
    vec3 Position = getCameraPosition();

    float scaleFactor = 1.25;
    m = multiplymat4(translate(0.0, 0.0, -10), scale(fScale*scaleFactor));
    float fOuter = (fScale*scaleFactor);
    float fInner = fScale;

    glUniform1f(glGetUniformLocation(atmosphereShader, "fInnerRadius"), fInner);
    glUniform1f(glGetUniformLocation(atmosphereShader, "fOuterRadius"), fOuter);
    glUniform3f(glGetUniformLocation(atmosphereShader, "camPosition"), Position.x, Position.y, Position.z);
    glUniform1f(glGetUniformLocation(atmosphereShader, "time"), glfwGetTime());

    initMVP(atmosphereShader, m, v);

    glBindVertexArray (atmosphereVAO);
    glDrawArrays( GL_TRIANGLES, 0, planet.vertexNumber);
    glBindVertexArray(0);

}

任何帮助,或任何能向我指出正确方向的东西,都将受到赞赏.

Any help, or anything that can point me in the right direction is appreciated.

推荐答案

发现问题是由于相机位置计算错误和未考虑对象的模型空间引起的.我在此处上传了简化版的代码.

Found the problem was caused by incorrect calculation of the camera position and not taking into account the model space of the object. I uploaded a stripped down version of the code here.

希望这将对尝试实施Sean O'Neil大气层代码的所有人有所帮助.

Hopefully this will help anyone trying to implement Sean O'Neil's atmosphere code.

这篇关于GLSL大气散射不随变换缩放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆