我试图使用imageStore()函数在片段着色器中的一维纹理中检索所写的值。我正在生成随机点并在片段着色器中处理,用圆周生成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 values\n";
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 values\n";
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输出:绿色矩形是合法的三角形。和这是从一维纹理中检索到的值。。glGetTexImage()不会检索超过50分的任何数据,而在30-49点的情况下,我会丢失数据,但小于30分的数据会给出正确的三角形数量。
发布于 2018-08-18 18:50:25
你使用了错误的记忆屏障。你必须在障碍之后指定你打算如何使用内存。
您正在使用glGetTexImage访问数据,因此根据OpenGL 4.6核心剖面规范第7.13节“着色内存访问”,您必须使用(强调我的):
GetTexImage:通过Tex(Sub)Image*、ClearTex*Image、CopyTex*或CompressedTex*、写入纹理,并在屏障完成前启动所有着色器写入后再通过读取。
https://stackoverflow.com/questions/51911519
复制相似问题