我正在尝试为一些体积效果生成一个3D Worley噪声纹理。我只是生成一组随机点,对于每个碎片,我将找到最近的点,并获得碎片和像素之间的距离。然后,该距离被用作图像的最终颜色。结果在2D中看起来像这样:
当我生成一个2D纹理时,这效果非常好。当我试图生成一个3D纹理时,我开始遇到一些问题。
现在,我将3D纹理的每个切片作为颜色附件进行附加,并使用着色器对其进行写入。代码如下:
产生噪声的功能(注:此代码假定宽度、高度和深度都相等):
void WorleyGenerator::GenerateWorley3D(int numPoints, Texture3D* texture, PrimitiveShape* quad, unsigned int nativeWidth, unsigned int nativeHeight)
{
int resolution = texture->GetWidth();
glViewport(0, 0, resolution, resolution);
glDisable(GL_CULL_FACE);
frameBuffer->Bind();
shader3D->Bind();
shader3D->SetFloat("uResolution", resolution);
shader3D->SetInt("uNumWorleyPoints", numPoints); // Tell shader how many points we have
// Generate random points and pass them ot shader
for (int i = 0; i < numPoints; i++)
{
shader3D->SetFloat3("uPointData[" + std::to_string(i) + "]", glm::vec3(Utils::RandInt(0, resolution), Utils::RandInt(0, resolution), Utils::RandInt(0, resolution)));
}
// Render to each "slice" of the texture
for (int z = 0; z < resolution; z++)
{
shader3D->SetInt("uCurrentSlice", z);
glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, texture->GetID(), 0, z);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
quad->Draw();
}
frameBuffer->Unbind();
glViewport(0, 0, nativeWidth, nativeHeight);
}
我的片段着色器:
# version 420
in vec2 mTextureCoordinates;
out vec4 oColor;
uniform int uCurrentSlice;
uniform float uResolution;
uniform int uNumWorleyPoints;
uniform vec3 uPointData[256];
void main()
{
vec3 fragPos = vec3(gl_FragCoord.xy, uCurrentSlice) / uResolution; // Convert frag pos to range 0 - 1
// Find closest point's distance
float closestDist = 100000.0f;
// Get closest point for red channel
for (int i = 0; i < uNumWorleyPoints; i++)
{
vec3 p = uPointData[i] / uResolution; // Convert point to range 0 - 1
float dist = distance(fragPos, p);
if (dist < closestDist)
{
closestDist = dist;
}
}
oColor = vec4(closestDist, closestDist, closestDist, 1.0f);
}
现在,为了测试我的代码,我将把3D纹理的每个切片保存到一个BMP文件:
void Utils::SaveTexture3DAsBMP(const std::string& savePath, Texture3D* texture)
{
unsigned int size = texture->GetWidth() * texture->GetHeight() * 4;
float* data = new float[size];
for (int z = 0; z < texture->GetDepth(); z++)
{
glGetTextureSubImage(texture->GetID(), 0, 0, 0, z, texture->GetWidth(), texture->GetHeight(), z, GL_RGBA16F, GL_FLOAT, size, data);
stbi_write_bmp((savePath + std::to_string(z) + ".bmp").c_str(), texture->GetWidth(), texture->GetHeight(), 4, data);
}
delete[] data;
}
保存的图像的结果如下所示:
而且,每个切片都是完全相同的,这是永远不应该发生的。
我怀疑我没有正确地写入切片,或者我保存图像的代码是错误的。
任何帮助都将不胜感激!
1条答案
按热度按时间yxyvkwin1#
我的问题不在于纹理,而在于我是如何保存图像的。我改变了我的纹理保存功能:
对此: