gpt4 book ai didi

c++ - 将 float 组作为 3D 纹理传递给 GLSL 片段着色器

转载 作者:行者123 更新时间:2023-11-28 05:55:38 26 4
gpt4 key购买 nike

我正在尝试实现基于光线转换的体积渲染,因此我需要将 float 组作为纹理 (Sampler3D) 传递给片段着色器。我有一个包含所有体素的体积数据结构。每个体素都包含一个密度值。因此,为了进行处理,我将这些值存储到一个 float 组中。

//initialize glew, initialize glfw, create window, etc.

float* density;
density = new float[volume->size()];

for (int i = 0; i < volume->size(); i++){
density[i] = volume->voxel(i).getValue();
}

然后我尝试创建和绑定(bind)纹理。

glGenTextures(1, &textureHandle);
glBindTexture(GL_TEXTURE_3D, textureHandle);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage3D(GL_TEXTURE_3D, 0, GL_LUMINANCE, volume->width(),
volume->height(), volume->depth(), 0, GL_LUMINANCE, GL_FLOAT, density);

在我的渲染循环中,我尝试将纹理加载到统一的 Sampler3D。

glClearColor(0.4f, 0.2f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glActiveTexture(GL_TEXTURE0);
GLint gSampler = glGetUniformLocation(shader->shaderProgram, "volume");
glUniform1i(gSampler, 0);

cube->draw();

所以基本思想是在顶点着色器中计算光线转换的当前位置和方向。

in vec3 position;

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

uniform vec4 cameraPos;

out vec3 pos;
out vec3 dir;

void main(){
gl_Position = projection * view * model * vec4(position, 1.0);
pos = position;
dir = pos - (inverse(model) * cameraPos).xyz;
}

这似乎运作良好,到目前为止一切顺利。片段着色器看起来像这样。我沿射线采集了一些样本,密度值最大的样本将作为红、绿、蓝颜色。

#version 330 core

in vec3 pos;
in vec3 dir;

uniform sampler3D volume;

out vec4 color;

const float stepSize = 0.008;
const float iterations = 1000;

void main(){

vec3 rayDir = normalize(dir);
vec3 rayPos = pos;

float src;
float dst = 0;
float density = 0;

for(int i = 0; i < iterations; i++){

src = texture(volume, rayPos).r;
if(src > density){
density = src;
}

rayPos += rayDir * stepSize;

//check whether rays are within bounds. if not -> break.

}
color = vec4(density, density, density, 1.0f);
}

现在我尝试插入一些小的调试断言。

if(src != 0){
rayPos = vec3(1.0f);
break;
}

但是 src 似乎在每个像素的每次迭代中都为 0。这让我得出采样器设置不正确的结论。调试 C++ 代码,在将密度数组传递给着色器之前,我得到了正确的密度数组值,所以我猜一定是缺少一些 opengl 函数。提前致谢!

最佳答案

glTexImage3D(GL_TEXTURE_3D, 0, GL_LUMINANCE, volume->width(), volume->height(), volume->depth(), 0, GL_LUMINANCE, GL_FLOAT, density);

除非这个密度在 [0, 1] 范围内,否则这几乎肯定不是您想要的。

GL_LUMINANCE,用作 internal format 时(glTexImage3D 的第三个参数,意味着 OpenGL 纹理数据中的每个像素都将包含一个 normal integer。所以如果你想要一个浮点值,你我有点不走运。

正确的做法是明确声明数据的类型和像素大小。 Luminance 在 3.1 中从核心 OpenGL 配置文件中删除,所以今天的方法是使用 GL_R32F 作为您的内部格式。这声明每个像素包含一个值,并且该值是一个 32 位 float 。

如果你真的需要跨 RGB channel 传播值,你可以使用 texture swizzling来完成那个。您可以设置一个 swizzle mask 以将红色组件广播到您喜欢的任何其他 channel 。

glActiveTexture(GL_TEXTURE0);
GLint gSampler = glGetUniformLocation(shader->shaderProgram, "volume");
glUniform1i(gSampler, 0);

我听说绑定(bind)纹理也是一个好主意。你知道,如果你真的想从中阅读 ;)

关于c++ - 将 float 组作为 3D 纹理传递给 GLSL 片段着色器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34215265/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com