如何分两个阶段编写 OpenGL 片段着色器?

如何解决如何分两个阶段编写 OpenGL 片段着色器?

我正在编写一个程序,用于绘制 Mandelbrot 集。对于每个像素,我运行一个函数,它返回一个介于 0 和 1 之间的激活数。目前,这是在片段着色器中完成的,激活是我的颜色。

但是想象一下你放大分形,突然间你能在屏幕上看到的所有激活值都在 0.87 到 0.95 之间。你看不出区别。

我正在寻找一种方法来首先计算所有激活并将它们存储在一个数组中,然后根据该数组选择颜色。出于性能原因,这两者都需要在 GPU 上运行。

解决方法

所以你需要找到你渲染的图片的最小和最大强度。这不能在一次绘制中完成,因为这些值是非本地的。一种可能的方法是递归地应用将图像缩小一半的管道,计算 2x2 正方形的最小值和最大值并存储它们,例如在 RG 纹理中(一种 mipmap 生成,使用 min/max 而不是平均颜色)。最后,您有一个 1x1 纹理,其中包含图像的唯一像素中的最小值和最大值。您可以在将激活值映射到颜色的最终渲染中对该纹理进行采样。

,

我通过创建一个新的 gll 程序并将计算着色器附加到它来解决了我的问题。

unsigned int vs = CompileShader(vertShaderStr,GL_VERTEX_SHADER);
unsigned int fs = CompileShader(fragShaderStr,GL_FRAGMENT_SHADER);
unsigned int cs = CompileShader(compShaderStr,GL_COMPUTE_SHADER);

glAttachShader(mainProgram,vs);
glAttachShader(mainProgram,fs);
glAttachShader(computeProgram,cs);

glLinkProgram(computeProgram);
glValidateProgram(computeProgram);

glLinkProgram(mainProgram);
glValidateProgram(mainProgram);

glUseProgram(computeProgram);

然后,在渲染循环中,我切换程序并运行计算着色器。

glUseProgram(computeProgram);
    glDispatchCompute(resolutionX,resolutionY,1);
    glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(mainProgram);

    /* Drawing the whole screen using the shader */
    glDrawArrays(GL_TRIANGLE_STRIP,4);

    /* Poll for and process events */
    glfwPollEvents();
    
    updateBuffer();
    Update();

    /* Swap front and back buffers */
    glfwSwapBuffers(window);

我通过着色器存储缓冲区将数据从计算着色器传递到片段着色器。

void setupBuffer() {
    glGenBuffers(1,&ssbo);
    glBindBuffer(GL_SHADER_STORAGE_BUFFER,ssbo);
    glNamedBufferStorage(ssbo,sizeof(float) * (resolutionX * resolutionY + 

    SH_EXTRA_FLOATS),&data,GL_MAP_WRITE_BIT | GL_MAP_READ_BIT | GL_DYNAMIC_STORAGE_BIT); //sizeof(data) only works for statically sized C/C++ arrays.
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER,1,ssbo);
}

void updateBuffer() {
    float d[] = { data.min,data.max };
    glNamedBufferSubData(ssbo,2 * sizeof(float),&d);
}

在计算着色器中,我可以像这样访问缓冲区:

layout(std430,binding = 1) buffer bufferIn
    {
        float min;
        float max;
        float data[];
    };

layout(std430,binding = 1) buffer destBuffer
{
    float min;
    float max;
    float data[];
} outBuffer;

void main() {
    screenResolution;
    int index = int(gl_WorkGroupID.x + screenResolution.x * gl_WorkGroupID.y);
    dvec2 coords = adjustCoords();

    dvec4 position = rotatedPosition(coords);

    for (i = 0; i < maxIter; i++) {
        position = pow2(position);
        double length = lengthSQ(position);
        if (length > treashold) {
            float log_zn = log(float(length)) / 2.0;
            float nu = log(log_zn / log(2.0)) / log2;
            float iterAdj = 1.0 - nu + float(i);
            float scale = iterAdj / float(maxIter);
            if (scale < 0)
                data[index] = -2;
            data[index] = scale;
            if (scale > max) max = scale;
            if (scale < min && scale > 0) min = scale;
            return;
        }
    }
    data[index] = -1;
};

最后,在片段着色器中,我可以像这样读取缓冲区:

layout(std430,binding = 1) buffer bufferIn
{
    float min;
    float max;
    float data[];
};

if (data[index] == -1) {
    color = notEscapedColor;
    return;
}
float value = (data[index] - min) / (max - min);
if (value < 0) value = 0;
if (value > 1) value = 1;

Here is the code in its entirety.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res