GLSL 大气散射不随变换缩放

2024-01-13

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

我有实际的散射方程,但对于大多数相机位置来说,大气的内半径与球体的外半径并不对齐。我知道这是因为大气层的半径比行星球体大,但我似乎无法让它正确缩放。

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

这里模型被缩放和平移。大气层偏离了相机的中心,内部大气层仍然没有与行星对齐。

这是顶点着色器,它本质上是一个直通着色器

#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);
}

如果需要的话,这里是绘制气氛的代码。绘制行星的代码基本上具有相同的转换(没有比例因子)。

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);

}

任何帮助,或者任何可以指引我正确方向的事情,我都会感激不尽。


发现问题是由于相机位置计算不正确并且没有考虑物体的模型空间引起的。我上传了代码的精简版本here https://github.com/TJGreen0211/gl_tests/tree/master/atmosphere.

希望这能帮助任何尝试实施 Sean O'Neil 的大气代码的人。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GLSL 大气散射不随变换缩放 的相关文章

  • 更改 GLUT 调用以与 MFC/C++ 一起使用

    我有一个使用 GLUT 进行 OpenGL 渲染的程序 现在我需要它位于 MFC 项目内部 以便它可以与另一个程序组件一起使用 我已经按照这个教程进行操作 http www codeguru com cpp g m opengl openf
  • glDrawElements 只绘制半个四边形

    这是我的功能 void Object draw2 if mIsInitialised return Tell OpenGL about our vertex and normal data glEnableClientState GL VE
  • SSBO 是更大的 UBO?

    我目前正在 OpenGL 4 3 中使用 UBO 进行渲染 以将所有常量数据存储在 GPU 上 诸如材料描述 矩阵等内容 它可以工作 但是 UBO 的小尺寸 我的实现为 64kB 迫使我多次切换缓冲区 减慢渲染速度 我正在寻找类似的方法来存
  • 简单的openGL程序无法在ubuntu中链接

    我正在尝试进入 opengl 编程 但无法编译我的第一个非常非常简单的程序 链接过程每次都会失败 我发现这个答案 https stackoverflow com questions 859501 learning opengl in ubu
  • 有没有好的 GLSL 哈希函数?

    所以我对这个问题的古老评论仍然得到了支持 GLSL rand 这一行代码的起源是什么 https stackoverflow com questions 12964279 whats the origin of this glsl rand
  • OpenGL:顶点越多,性能越慢

    我正在开发一个程序的一部分 其中给定 xyz 坐标集合 制作 3D 模型 我已经完成了这张图片所需的所有功能 即平移 旋转 缩放 但是给出的 xyz 坐标越多 程序运行速度就越慢 我的程序在处理 29 000 个坐标时运行得非常流畅 但当我
  • 在 QML 中控制纹理 3D 对象的不透明度

    我对 QML 中的 Qt 3D 有点陌生 我正在尝试控制 Qt 3D 的不透明度textured3D 对象 我正在使用简单qml3d https github com tripolskypetr simpleqml3d测试项目来做到这一点
  • LibGDX纹理混合与OpenGL混合功能

    在 libGdx 中 我试图创建一个成形纹理 采用完全可见的矩形纹理并将其遮罩以获得成形纹理 如下所示 在这里我在矩形上测试它 但我想在任何形状上使用它 我调查过本教程 http www learnopengles com tag addi
  • OpenGL:VAO 和 VBO 对于大型多边形渲染任务是否实用?

    如果您想渲染一次在视锥体中包含数千个多边形的大型景观 并且用户的视点不断变化 那么使用 VAO 或 VBO 是否实用 我的意思是 每次玩家的位置或摄像机旋转发生变化时 您都必须重新计算顶点数据 以便正确剔除不再可见的任何顶点或场景 以保持良
  • glm 中矩阵值的顺序不正确?

    我开始使用GLM http glm g truc net通过 OpenGL 3 和 GLSL 进行数学运算的库 我需要正交投影来绘制 2D 图形 所以我编写了这个简单的代码 glm mat4 projection 1 0 projectio
  • OpenGL:始终相同的颜色

    我正在 Windows 上编写一个程序 使用c opengl 2 1 and SDL我在顶点颜色方面遇到了一些问题 我在用着glColor3f设置每个顶点集的颜色 但它似乎不起作用 无论我选择什么颜色 我都会将每个顶点绘制为红色 我检查了传
  • 渲染缓冲区大于窗口大小 - OpenGL

    我正在尝试绘制大于屏幕尺寸 即 320x480 的渲染缓冲区 512x512 执行 glReadPixels 后 图像看起来是正确的 除非图像的尺寸超过了屏幕尺寸 在本例中 超过了水平 320 和垂直 480 是什么原因导致这种异常现象呢
  • 按像素值偏移 gl_Position 或 gl_Vertex

    我的属性包含像素值 我想用这个属性值来偏移我的 gl vertex 问题是我的 gl vertex 以世界单位为单位 而 offset attribute 以像素为单位 如果我将屏幕尺寸作为统一发送 然后将像素转换为 1 到 1 值 并将其
  • 创建并使用我自己的纹理图集的 mipmap

    我目前正在使用自动 mipmap 生成 C OpenTK GL GenerateMipmap GenerateMipmapTarget Texture2D 我使用的纹理平铺为 16px 的块 所以我的问题是 是否可以使用不会缩小至 1x1
  • 如何在多采样纹理上渲染帧缓冲区对象?

    我目前有一个使用多个通道的渲染引擎 其中图像的各个部分在纹理上渲染 然后使用着色器进行组合 它有效 现在我想激活多重采样 我在这里读到 http www opengl org wiki Framebuffer Object Examples
  • 具有交错缓冲区的 openGL glDrawElements

    到目前为止 我只使用了 glDrawArrays 并希望转向使用索引缓冲区和索引三角形 我正在绘制一个有点复杂的对象 其中包含纹理坐标 法线和顶点坐标 所有这些数据都收集到一个交错的顶点缓冲区中 并使用类似于以下的调用进行绘制 假设所有血清
  • 渲染到一个颜色通道而不影响其他通道

    使用 OpenGL 任何版本 如何通过一次仅影响一个颜色通道来渲染到帧缓冲区对象 例如 我的帧缓冲区对象具有 GL BGRA 布局 现在我想执行一些渲染命令 这些命令应该只改变红色通道 因此 如果片段用颜色 204 0 0 0 渲染并且像素
  • WGL:没有双缓冲 + 多重采样 = 失败?

    我通常使用创建像素格式wglChoosePixelFormatARB 与这些论点 除其他外 WGL DOUBLE BUFFER ARB GL TRUE WGL SAMPLE BUFFERS ARB GL TRUE WGL SAMPLES A
  • 带有 std::vector 的 VBO

    我用 C 和 OpenGL 编写了一个模型加载器 我用过std vectors 来存储我的顶点数据 但现在我想将其传递给glBufferData 但是数据类型却截然不同 我想知道是否有办法可以相互转换std vector至已记录的const
  • OpenGL纹理渲染与原始不匹配

    我正在尝试使用 OpenGL 渲染纹理 我用作测试的纹理是白色背景上的一堆黑色矩形 如下所示 然而 在渲染时 纹理似乎被复制并叠加在其自身之上多次 我使用以下方法设置场景 std string vertexSource ShaderLoad

随机推荐

  • 如何在python中给定起始网络地址获取下一个网络地址

    python 有没有办法从给定的起始网络地址获取下一个网络地址 有多种方法可以使用以下命令获取下一个主机 IPipaddress模块 但是有没有办法获得下一个网络本身 例如 如果我的起始网络地址10 1 0 0 16 然后在每次迭代中我想获
  • jQuery 是否在内部缓存元素?

    我知道 jQuery 不会缓存元素集合 f ex 调用 myclass html hello myclass html bye 会让 jQuery 爬 DOM 两次 但是缓存的 DOM 节点又如何呢 var elems document q
  • 如何通过 Chef 在 Tomcat 7 食谱上上传 WAR 文件?

    我正在尝试在由 CHEF 上的食谱安装的 Tomcat 7 上部署一个 War 文件 但是 我在任何论坛上都找不到我的问题的答案 我不知道该怎么做 我使用的是 Ubuntu 服务器 12 10 我正在使用的食谱是https github c
  • 在 CosmosDB 存储过程中创建和比较日期

    对于 CosmosDB 存储过程及其处理的指导有限new Date 以及日期的比较 以下代码是一个 CosmosDB 存储过程 用于在给定时间后 冻结 文档的写入 该物业currentDoc FreezeDate采用 ISO 8601 格式
  • 响应式网站随 iPad 一起放大

    看来 当我通过 iPad 最新一代 访问我的网站时 它会以横向模式正确启动响应式网站 当我切换到纵向时 我可以看到网站调整得很好 而且看起来也不错 当我再次切换回横向时 该网站似乎放大了一点 需要缩小 我在页面中有以下代码来尝试解决此问题
  • 通过 css 伪 :after 清除两者的一些奇怪的事情

    检查这段代码 HTML h1 class one Sometext over here h1
  • 无法在核心管道中的中间件中实现try-catch的可调用catch

    我已将自定义中间件添加到我的Startup类 以下示例here https learn microsoft com en us aspnet core fundamentals middleware tabs aspnetcore2x wr
  • 我使用 pyinstaller 创建的 .exe 文件适用于 Windows 10,但不适用于 Windows 7

    当我在 Windows 7 上运行程序时 出现以下错误 加载 Python DLL C Users msi AppData Local Temp MEI91442 python38 dll 时出错 没有生成错误消息 FormatMessag
  • 如何在 Hazelcast 地图存储中实例化对象(Jdbc 模板)

    我正在尝试在mapStore 内自动装配jdbc 模板 但我遇到了空指针异常 我研究了很多例子 但仍然无法解决这个问题 这是我的主要课程 import org springframework boot SpringApplication i
  • 禁用反应导航中的后退按钮

    我正在使用反应本机导航 反应导航 StackNavigator 它从登录页面开始贯穿应用程序的整个生命周期 我不想有返回选项 返回到登录屏幕 有谁知道如何在登录屏幕后将其隐藏在屏幕上 顺便说一句 我还使用以下方法将其隐藏在登录屏幕中 con
  • 如何将窗体变成完全透明的32位alpha?

    我用来创建一个完全透明的表单 但是 png 和 32 位图像不会混合到该表单中 并且图像无法正确显示其透明度 我明白了here http melander dk articles alphasplash 但我不能在上面放按钮 除图像背景外
  • 如何使用 Directory.EnumerateFiles 排除隐藏文件和系统文件

    我正在枚举目录中的所有文件 以便稍后处理它们 我想排除隐藏文件和系统文件 这是我到目前为止所拥有的 IEnumerable
  • 用于撰写的寻呼机指示器

    我正在使用伴奏者的寻呼指示器 它工作正常 但不可定制 我想设置屏幕上应显示的确切数量的点 并且这些点的大小应在卷轴上进行配置 有另一个问题 https stackoverflow com questions 71998748 how to
  • Google Api Auth Http 模块错误

    我正在开发第一个使用 Google Api for Calendar 的应用程序 我读过谷歌的例子 https developers google com google apps calendar instantiate https dev
  • 如何构建一个离线工作的 php mysql 应用程序

    我有一个网络应用程序 将数据在线存储在 MySQL 数据库中 它还使用 PHP 代码检索数据 在服务器上执行计算并将结果发送回用户 数据非常简单 从数据库读取并在服务器端操作的名称 描述 价格 增值税 每小时费用 客户通常在互联网连接较差或
  • 为什么ListCellRenderer中需要removeAll()?

    这是我的代码 public class MyRender extends JPanel implements ListCellRenderer ImageIcon on img JLabel name new JLabel JLabel i
  • 处理 docmd.applyfilter 无结果

    我有一个 Access 应用程序 我在其中使用搜索功能 我在表单上有一个文本框和一个搜索按钮 它对用户在文本框中输入的任何内容进行通配符搜索 并在其他控件 文本和组合框 中显示记录 为了实现这一目标 我正在使用DoCmd ApplyFilt
  • 为什么 Composer 抱怨 ext-mongo 扩展?

    当我尝试使用composer安装doctrine mongodb odm bundle和doctrine mongodb时 它会抛出错误 composer require doctrine mongodb odm bundle doctri
  • 在 Gatsby 中设置环境变量

    我使用了这个教程 https github com gatsbyjs gatsby blob master docs docs environment variables md https github com gatsbyjs gatsb
  • GLSL 大气散射不随变换缩放

    我正在尝试在 GLSL 版本 4 10 中实现大气散射 我正在改编此 Shadertoy 着色器中的着色器https www shadertoy com view lslXDr https www shadertoy com view ls