使用片段着色器写入 1D 纹理后从 1D 纹理读回不起作用
Reading back from 1D textures after writing into it with a fragment shader is not working
我正在尝试使用 imageStore(( 函数检索我在片段着色器中的 1D 纹理中写入的值。我正在生成随机点并在片段着色器中进行处理,以使用圆周生成 delaunay 三角测量。当我生成一定大小的点(小于 30(时,从纹理读取是有效的,但是当我增加大小时,它返回零。 这是我存储的片段着色器的一部分:
uniform layout(binding = 1, rgba32f) writeonly image1D tex1;
… // more code
if (flag)
{
color = vec3(0.0, 1.0, 0.0);
int index = 0;
for (int i = 0; i < b; i++)
index += (size - i - 1) * i;
index += a * (size - b - 1) + (i_uv.x + 1) - 1;
imageStore(tex1, index, vec4(a, b, c, 1.0));
}
我的应用代码是这样的:
imageSize = 0;
int stride{ size - 1 };
for (size_t i{ 0 }; i < size - 1; i++)
imageSize += (stride - i) * i;
glCreateTextures(GL_TEXTURE_1D, 1, &image);
glTextureStorage1D(image, 1, GL_RGBA32F, imageSize);
pixels = new vec4[imageSize];
//Reading back from texture (This part goes outside my game loop)
glBindImageTexture(1, image, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
shaderFBO.use();
shaderFBO.setUniformi(ShaderType::FRAGMENT_SHADER, 0, size);
shaderFBO.setUniform2v(ShaderType::FRAGMENT_SHADER, 1, vec2(Window::current->getWidth(), Window::current->getHeight()));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
glBindTexture(GL_TEXTURE_1D, image);
glGetTexImage(GL_TEXTURE_1D, 0, GL_RGBA, GL_FLOAT, pixels);
std::cout << "nTexture valuesn";
size_t count{ 0 };
for (size_t i{ 0 }; i < imageSize; i++)
{
if (pixels[i].a != 0)
{
std::cout << pixels[i] << std::endl;
count++;
}
}
std::cout << count << std::endl;
编辑: 我将放置我的完整顶点和片段着色器,以及应用程序代码来帮助我检查我是否错过了相关内容
顶点着色器:
#version 450 core
out gl_PerVertex
{
vec4 gl_Position;
};
void main()
{
vec2 p[4] = vec2[4]
(
vec2(-1.0, -1.0),
vec2( 1.0, -1.0),
vec2(-1.0, 1.0),
vec2( 1.0, 1.0)
);
gl_Position = vec4(p[gl_VertexID], 0.0, 1.0);
}
片段着色器:
#version 450 core
out vec4 FragColor;
layout(binding = 0) uniform sampler1D tex0; // Buffer storing random points
uniform layout(binding = 1, rgba32f) writeonly image1D tex1; // Buffer to store the indices of legal triangles
layout(location = 0) uniform int size;
layout(location = 1) uniform vec2 u_resolution;
vec2 circumcenter(vec2 A, vec2 B, vec2 C, out bool f)
{
vec2 P1 = (A + B) / 2.0;
vec2 P2 = (A + C) / 2.0;
float a1 = -A.x + B.x;
float b1 = A.y - B.y;
float a2 = -A.x + C.x;
float b2 = A.y - C.y;
float c1 = a1*P1.x - b1*P1.y;
float c2 = a2*P2.x - b2*P2.y;
float det = a1*b2 - a2*b1;
vec2 circum = vec2(0.0);
f = false;
if (det != 0)
{
float x = (b2*c1 - b1*c2) / det;
float y = (a2*c1 - a1*c2) / det;
circum = vec2(x, y);
f = true;
}
return circum;
}
void main()
{
vec2 st = gl_FragCoord.xy / u_resolution;
ivec2 i_st = ivec2(floor(st * size));
vec2 f_st = fract(st * size);
vec3 color = vec3(0.0);
if (i_st.y > i_st.x && i_st.y < size - 1)
{
// Positions of the random points buffer (a, b, c)
int a = i_st.x;
int b = i_st.y;
ivec2 i_uv = ivec2(floor(f_st * (size - b - 1)));
int c = i_uv.x + b + 1;
// Points of the triangle
vec2 A = texelFetch(tex0, a, 0).xy;
vec2 B = texelFetch(tex0, b, 0).xy;
vec2 C = texelFetch(tex0, c, 0).xy;
bool flag;
vec2 cir = circumcenter(A, B, C, flag);
if (flag)
{
float radius = distance(cir, A);
// Checking if any other point is inside of the circumscribe circle
for (int i = 0; i < size; i++)
{
if (i == a || i == b || i == c)
continue;
vec2 P = texelFetch(tex0, i, 0).xy;
float dist = distance(cir, P);
if (dist < radius)
{
flag = false;
break;
}
}
if (flag)
{
color = vec3(0.0, 1.0, 0.0); // Painting the fargments that correspond to legal triangles
int index = 0;
for (int i = 0; i < b; i++)
index += (size - i - 1) * i;
index += a * (size - b - 1) + (i_uv.x + 1) - 1;
memoryBarrier();
imageStore(tex1, index, vec4(a, b, c, 1.0)); // Storing indices of legal triangles
}
}
}
else
color += 1.0;
FragColor = vec4(color, 0.0);
}
应用代码:
#include "../../Classes/Renderer/Core.h"
#include "../../Classes/Renderer/Shader.h"
#include "../../Classes/Renderer/Input.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
class DT
: public Core
{
public:
virtual void Start() override
{
srand(time(nullptr));
shader.addShader("C:/dev/RendererOpenGL/RendererOpenGL/src/Tesis/simpleTri.vert", ShaderType::VERTEX_SHADER);
shader.addShader("C:/dev/RendererOpenGL/RendererOpenGL/src/Tesis/simpleTri.frag", ShaderType::FRAGMENT_SHADER);
// Compute Buffer size to store indices of legal triangles
imageSize = 0;
int stride{ size - 1 };
for (size_t i{ 0 }; i < size - 1; i++)
imageSize += (stride - i) * i;
glCreateTextures(GL_TEXTURE_1D, 1, &image);
glTextureStorage1D(image, 1, GL_RGBA32F, imageSize);
pixels = new vec4[imageSize];
glCreateTextures(GL_TEXTURE_1D, 1, &texture1D);
glTextureStorage1D(texture1D, 1, GL_RG32F, size);
data = new vec2[size];
// Genereating random points
for (size_t i{ 0 }; i < size; i++)
{
float x = static_cast<float>(rand()) / RAND_MAX;
float y = static_cast<float>(rand()) / RAND_MAX;
data[i] = vec2(x, y);
//std::cout << i << ": " << data[i] << std::endl;
}
glTextureSubImage1D(texture1D, 0, 0, size, GL_RG, GL_FLOAT, data);
glBindTextureUnit(0, texture1D);
glBindTexture(GL_TEXTURE_1D, texture1D);
glBindImageTexture(1, image, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
// Rendering once to compute legal triangles
shader.use();
shader.setUniformi(ShaderType::FRAGMENT_SHADER, 0, size);
shader.setUniform2v(ShaderType::FRAGMENT_SHADER, 1, vec2(Window::current->getWidth(), Window::current->getHeight()));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
glBindTexture(GL_TEXTURE_1D, image);
glGetTexImage(GL_TEXTURE_1D, 0, GL_RGBA, GL_FLOAT, pixels);
std::cout << "nTexture valuesn";
size_t count = 0;
for (size_t i{ 0 }; i < imageSize; i++)
{
if (pixels[i].a != 0)
{
std::cout << pixels[i] << std::endl;
count++;
}
}
std::cout << count << std::endl;
}
virtual void Update() override
{
}
virtual void End() override
{
shader.delete_shader();
glDeleteTextures(1, &texture1D);
glDeleteTextures(1, &imageSize);
delete[] data;
delete[] pixels;
}
private:
Shader shader;
vec2* data;
const int size{ 20 };
GLuint texture1D;
GLuint image;
size_t imageSize;
vec4 *pixels;
};
#if 1
CORE_MAIN(DT)
#endif
输出: 绿色矩形是合法三角形和 这是从 1D 纹理中检索到的值。glGetTexImage(( 不会检索任何超过 50 个点的数据,对于 30 到 49 个点,我丢失了数据,但少于 30 个点时,我得到了正确数量的三角形。
您使用了错误的内存屏障。您必须指定在屏障之后打算如何使用内存。
您正在使用glGetTexImage
来访问数据,因此根据OpenGL 4.6核心配置文件规范第7.13节"着色器内存访问",您必须使用(强调我的(:
TEXTURE_UPDATE_BARRIER_BIT
: 写入 通过Tex(Sub)Image*
、ClearTex*Image
、CopyTex*
或CompressedTex*
的纹理, 并在屏障不会执行后通过GetTexImage
读取直到在屏障完成之前启动所有着色器写入。
相关文章:
- 1d 智能指针不适用于语法 (*)++
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- C++使用数组作为多维数组,尽管将其初始化为带有指针的 1D
- SFML纹理像播放器
- OpenGL大的3D纹理(>2GB)非常慢
- UE4-如何在给定4个屏幕坐标的情况下缩放纹理或材质
- 着色器纹理值与创建纹理时写入的值不同
- OpenGL将纹理四边形渲染为(0,0)
- 宽度为奇数的16位纹理为片状
- 使用 CUDA 和纹理进行图像减法
- 在不使用统一的情况下将纹理传递给 GLSL 着色器?
- 将使用太多的纹理插值器 - 带旋转的着色器
- dx11 渲染到纹理仅显示透明颜色
- OpenGL 4.3 错误地将第 4 个纹理坐标映射到与第 3 个纹理坐标相同的位置
- 1d.exe找不到SFML文件?
- 1D中的非均匀FFT正向和反向测试
- 使用片段着色器写入 1D 纹理后从 1D 纹理读回不起作用
- opengl 1D 纹理:用任意浮点值填充
- 使用栅格数据和1D纹理图在opengl中创建等高线图