Shader doesn't write anything for picking by id - opengl

I am trying to implement picking by an int id, but it looks like my shader doesn't write anything, althought I can read the clear color properly.
vs, I skipped completely any matrix for debugging:
#version 330
#include semantic.glsl
layout (location = POSITION) in vec3 position;
uniform Transform0
{
mat4 view;
mat4 proj;
mat4 viewProj;
};
uniform Transform1
{
mat4[TRANSFORM1_SIZE] models;
};
uniform Parameters
{
// x = mesh baseVertex
// y = selected
// z = active
// w = id
ivec4[INDICES_SIZE] params;
};
out Block
{
flat int id;
} outBlock;
int getIndex()
{
int iBegin = 0;
int iEnd = params.length() - 1;
int l = iBegin;
int r = iEnd;
int i = 0;
if(params.length > 1)
{
do
{
i = int(((l + r) / 2.0f));
if (l == (r - 1))
if (l == 0 && gl_VertexID <= params[l].x || gl_VertexID <= params[l].x && gl_VertexID > params[l - 1].x)
return l;
else if(gl_VertexID > params[l].x && gl_VertexID <= params[r].x)
return r;
else
return 0;
else if (gl_VertexID == params[i].x)
return i;
else if (gl_VertexID < params[i].x)
r = i;
else if (gl_VertexID > params[i].x)
l = i;
} while (l < r);
}
return 0;
}
void main()
{
int index = getIndex();
mat4 model = models[index];
//gl_Position = proj * (view * (model * vec4(position, 1)));
gl_Position = vec4(4.0 * float(gl_VertexID % 2) - 1.0, 4.0 * float(gl_VertexID / 2) - 1.0, 0.0, 1.0);
outBlock.id = params[index].w;
}
fs, hardcoded value for the moment, output is 0 (FRAG_COLOR), tried also 1 but nothing:
#version 330
#include semantic.glsl
// Outgoing final color.
layout (location = FRAG_COLOR) out int outputColor;
in Block
{
flat int id;
} inBlock;
void main()
{
//outputColor = inBlock.id;
outputColor = 9;
}
Init phase, I have one fbo, called RESOLVE, with 3 attachements, one depth, one float color on 0 and one integer for picking on 1. Fbo is complete:
gl3.glBindTexture(GL_TEXTURE_2D, textureName.get(Texture.RESOLVE_ID));
gl3.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
gl3.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
gl3.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl3.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl3.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl3.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl3.glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, EC.viewer.size.x, EC.viewer.size.y, 0, GL_RED_INTEGER, GL_INT, null);
gl3.glGenFramebuffers(Framebuffer.MAX - (samples == 1 ? 1 : 0), framebufferName);
gl3.glBindFramebuffer(GL_FRAMEBUFFER, framebufferName.get(Framebuffer.RESOLVE));
gl3.glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, textureName.get(Texture.RESOLVE_DEPTH), 0);
gl3.glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureName.get(Texture.RESOLVE_COLOR), 0);
gl3.glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textureName.get(Texture.RESOLVE_ID), 0);
if (gl3.glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
System.err.println("incomplete");
return false;
}
and render & reading, added also glFlush, glFinish and glPixelStorei but nothing:
gl3.glBindFramebuffer(GL_FRAMEBUFFER, framebufferName.get(Framebuffer.RESOLVE));
gl3.glDrawBuffer(GL_COLOR_ATTACHMENT1);
gl3.glClearBufferiv(GL_COLOR, 0, clearId.put(0, 0)); // we care clearing only red
gl3.glBindVertexArray(EC.meshManager.vertexArrayName.get(0));
gl3.glEnable(GL_DEPTH_TEST);
gl3.glUseProgram(program.name);
gl3.glDrawElements(GL_TRIANGLES, EC_Gl3MeshManager.ELEMENT_OPAQUE_COUNT, GL_UNSIGNED_INT, 0);
gl3.glDisable(GL_DEPTH_TEST);
gl3.glReadBuffer(GL_COLOR_ATTACHMENT1);
glm.vec._2.i.Vec2i window = new glm.vec._2.i.Vec2i(
EC.inputListener.mousePressed.getX(),
EC.viewer.size.y - EC.inputListener.mousePressed.getY() - 1);
System.out.println("window (" + window.x + ", " + window.y + ")");
gl3.glFlush();
gl3.glFinish();
gl3.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Get the red coordinate reading the pixel click from the color 1 buffer, we can use the clearId buffer
gl3.glReadPixels(window.x, window.y, 1, 1, GL_RED_INTEGER, GL_INT, clearId);
gl3.glReadBuffer(GL_COLOR_ATTACHMENT0);
As I said, if I clear with 10, I read 10, so that is working, the only problematic thing is my shader..
Can you spot the error, guys?
Edit: trying to debug, I am checking the attachment type on color 1
gl3.glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, clearId);
System.out.println("GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: " + clearId.get(0));
gl3.glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, clearId);
System.out.println("GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: " + clearId.get(0)+", tex: "+textureName.get(Texture.RESOLVE_ID));
I get:
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: 5890
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 14, tex: 14
5890 is GL_TEXTURE, name looks correct
tried to use glFramebufferTexture2D, but I still get GL_TEXTURE type instead GL_TEXTURE_2D
Edit 2: trying to read the depth component, is always 0

Shame on me, the problem was the depth test, since I forgot to clean the buffer it was never passing

Related

Compute shader can't get result image

I am using the compute shader to get a column of colors to match the conditions and I want to get the results for further processing. I want to get the output data in image1D imgOutput, but get_img can't get anything, did I do something wrong?
the texture in the first block has been generated before.
Shader spriteRowProgram, spriteColumnProgram;
unsigned int resultTexture = 0;
const std::string path = found::utils::Environment::GetRunPath();
const std::string sprite_row_path = path + "shaders/glfw_sprite_row.comp";
spriteRowProgram = Shader(sprite_row_path);
std::vector<GLfloat> get_img(qMax(TEX_WIDTH, TEX_HEIGHT) * 4);
glGenTextures(1, &resultTexture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_1D, resultTexture);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, qMax(TEX_WIDTH, TEX_HEIGHT), 0, GL_RGBA, GL_FLOAT, get_img.data());
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, texture);
spriteRowProgram.use();
glUniform1i(1, 1);
glBindImageTexture(1, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
glUniform1i(0, 0);
glBindImageTexture(0, resultTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
glClear(GL_COLOR_BUFFER_BIT);
spriteRowProgram.setInt("input_width", TEX_WIDTH);
spriteRowProgram.setInt("input_height", TEX_HEIGHT);
glDispatchCompute(TEX_WIDTH, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
#version 430 core
layout (local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, location = 0, binding = 0) uniform writeonly image1D imgOutput;
// texture samplers
layout(rgba32f, location = 1, binding = 1) uniform readonly image2D inputImage;
uniform int input_width;
uniform int input_height;
void main()
{
vec4 baseColor = imageLoad(inputImage, ivec2(0, 0));
bool alpha = baseColor.w == 1;
bool success = true;
for (int i = 0; i <= input_height; ++i)
{
vec4 current = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.x, i));
if (alpha) {
if (current.w > 0.99) continue;
else {
success = false;
break;
}
} else {
vec4 difference = baseColor - current;
success = abs(difference.x) < 0.01 && abs(difference.y) < 0.01 && abs(difference.z) < 0.01;
if (success) continue;
else {
break;
}
}
}
if (success) baseColor = ivec4(0.1, 0.1, 0.1, 0.1);
else baseColor = ivec4(1.0, 1.0, 1.0, 1.0);
imageStore(imgOutput, int(gl_GlobalInvocationID.x), baseColor);
}
One issue might be that if you want to access images after the compute shader, the argument for glMemoryBarrier should be GL_SHADER_IMAGE_ACCESS_BARRIER_BIT and not GL_SHADER_STORAGE_BARRIER_BIT.
So
spriteRowProgram.setInt("input_width", TEX_WIDTH);
spriteRowProgram.setInt("input_height", TEX_HEIGHT);
glDispatchCompute(TEX_WIDTH, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
should really be
spriteRowProgram.setInt("input_width", TEX_WIDTH);
spriteRowProgram.setInt("input_height", TEX_HEIGHT);
glDispatchCompute(TEX_WIDTH, 1, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

How to use GL_TEXTURE_2D_ARRAY with stb_image

I'm trying to create sprite animation with texture array. Right now I have follow code:
int width, height, depth;
stbi_set_flip_vertically_on_load(true);
byte_t* buffer = stbi_load(R"(.\fire.jpg)",
&width, &height, &depth, STBI_rgb_alpha);
if (buffer == nullptr) {
std::cerr << "Could not read texture" << std::endl;
return EXIT_FAILURE;
}
GLuint texture_id;
const GLenum target = GL_TEXTURE_2D_ARRAY;
SAFE_CALL(glGenTextures(1, &texture_id));
SAFE_CALL(glBindTexture(target, texture_id));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 1));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
const GLsizei tile_w_count = 6, tile_h_count = 6;
const GLsizei total_tiles = tile_w_count * tile_h_count;
const GLsizei tile_w = width / tile_w_count,
tile_h = height / tile_h_count;
std::cout << "Texture WxH: " << width << "x" << height;
std::cout << ", Tile WxH: " << tile_w << "x" << tile_h << std::endl;
SAFE_CALL(glTexStorage3D(target, 1, GL_RGBA8, tile_w, tile_h,
total_tiles));
SAFE_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, width));
SAFE_CALL(glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, height));
for (GLsizei i = 0; i < total_tiles; ++i) {
SAFE_CALL(glTexSubImage3D(
GL_TEXTURE_2D_ARRAY,
0,
0, 0, i,
tile_w, tile_h, 1,
GL_RGBA,
GL_UNSIGNED_BYTE,
buffer + (i * tile_w * tile_h * depth)
));
}
Fragment shader:
#version 460 core
in vec2 tex_coords;
out vec4 frag_color;
uniform sampler2DArray texture_0;
uniform int current_frame;
uniform int total_frames;
float actual_layer() {
return max(0, min(total_frames - 1,
floor(current_frame + 0.5)));
}
void main() {
frag_color = texture(texture_0, vec3(tex_coords, actual_layer()));
}
And seems like I incorrectly crop source texture, because when I run my program in Nsight debugger I saw follow:
Texture array:
Original image:
Is it issue with cropping source image, or issue with fragment shader? How to make sprite animation correctly?
You calculate the data offset incorrectly. The correct way would be:
Convert i to a 2-d index of the tile:
int ix = i % tile_w_count;
int iy = i / tile_w_count;
The x and y coordinates of its top-left pixel would be at
int x = ix*tile_w;
int y = iy*tile_h;
The offset can be calculated then by:
buffer + 4*(y*width + x)
Note that you shall use 4 instead of depth because stb returns the number of channels that was found in the file rather the number of the channels returned.

Why always produce 4 pictures in my qt opengl program?

Here is my code:
modify from qt example: Examples\Qt-5.14.2\quick\scenegraph\openglunderqml
void SquircleRenderer::init()
{
unsigned char* data = (unsigned char*)malloc(1200*4);
for(int i=0;i<600;i++)
{
data[i*4] = 0;
data[i*4+1] = 255;
data[i*4+2] = 0;
data[i*4+3] = 255;
}
for(int i=600;i<1200;i++)
{
data[i*4] = 0;
data[i*4+1] = 0;
data[i*4+2] = 255;
data[i*4+3] = 255;
}
if (!m_program) {
QSGRendererInterface *rif = m_window->rendererInterface();
Q_ASSERT(rif->graphicsApi() == QSGRendererInterface::OpenGL || rif->graphicsApi() == QSGRendererInterface::OpenGLRhi);
initializeOpenGLFunctions();
if (texs[0])
{
glDeleteTextures(1, texs);
}
glGenTextures(1, texs);
glBindTexture(GL_TEXTURE_2D, texs[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 30, 40, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
m_program = new QOpenGLShaderProgram();
m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute highp vec4 vertices;"
"varying highp vec2 coords;"
"void main() {"
" gl_Position = vertices;"
" coords = vertices.xy;"
"}");
m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment,
"varying highp vec2 coords;"
"uniform sampler2D inputImageTexture;"
"void main() {"
" gl_FragColor = texture2D(inputImageTexture, coords);"
"}");
m_program->bindAttributeLocation("vertices", 0);
m_program->link();
arrUni[0] = m_program->uniformLocation("inputImageTexture");
}
}
//! [4] //! [5]
void SquircleRenderer::paint()
{
// Play nice with the RHI. Not strictly needed when the scenegraph uses
// OpenGL directly.
m_window->beginExternalCommands();
m_program->bind();
m_program->enableAttributeArray(0);
float values[] = {
-1, 1,
1, 1,
-1, -1,
1, -1
};
// This example relies on (deprecated) client-side pointers for the vertex
// input. Therefore, we have to make sure no vertex buffer is bound.
glBindBuffer(GL_ARRAY_BUFFER, 0);
m_program->setAttributeArray(0, GL_FLOAT, values, 2);//values
//m_program->setUniformValue("t", (float) m_t);
qDebug()<<m_viewportSize.width()<<m_viewportSize.height()<<"\n";
glViewport(0, 0, m_viewportSize.width(), m_viewportSize.height());
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texs[0]);
glUniform1i(arrUni[0], 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
m_program->disableAttributeArray(0);
m_program->release();
m_window->endExternalCommands();
}
As the picture you can see,it produces 4 same pictures,could you tell me how to produce 1 picture fill the whole window?:
I tried so many methods, but it didn't work, I guess the problem exists in the values array or the glTexImage2D function.
Textures are mapped accross the [0, 1] range, and values outside of that range are modulo-looped back into it, which creates a repeating pattern. Interpreting the texture over the [-1, 1] range leads to what you are seeing since you are mapping exactly twice the UV range in both axises.
There's a few ways to fix this. But my personal preference for a full-framebuffer pass like this is to have the attribute be normalized, and then have it converted to the expected [-1, 1] range for the clip-space coordinate in the vertex shader:
float values[] = {
0.f, 1.f,
1.f, 1.f,
0.f, 0.f,
1.f, 0.f
};
gl_Position = vertices * 2.0 - vec4(1.0, 1.0,0.0,1.0);
Another common technique is to do away with the attribute buffer altogether, and use gl_VertexID to directly generate both the UVs and coordinates.

OpenGL - object outline

I'm trying to implement a selection-outline feature. This is what I get up to now.
As you can see, the objects are selected correctly when the mouse hovers and a contour is drawn around the selected object.
What I would like to do now is to outline the visible edges of the object in this way
In the image on the left is what I have now, and in the right image is what I want to achieve.
This is the procedure I use now.
void paintGL()
{
/* ... */
int w = geometry().width();
int h = geometry().height();
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0xFF);
setClearColor(Qt::GlobalColor::darkGray);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glStencilMask(0x00);
DrawGeometry();
if (HoveredSphere != RgbFromColorToString(Qt::GlobalColor::black))
{
glBindFramebuffer(GL_FRAMEBUFFER, addFBO(FBOIndex::OUTLINE));
{
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
DrawOutline(HoveredSphere, 1.0f - 0.025f);
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
glBindFramebuffer(GL_READ_FRAMEBUFFER, addFBO(FBOIndex::OUTLINE));
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFramebufferObject());
{
// copy stencil buffer
GLbitfield mask = GL_STENCIL_BUFFER_BIT;
glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, mask, GL_NEAREST);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilMask(0x00);
glDepthFunc(GL_LEQUAL);
DrawOutline(HoveredSphere, 1.0f);
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
}
update();
}
Where DrawGeometry draws all the objects, and DrawOutline draws the selected object scaled by the factor passed as the second parameter.
Thanks for any suggestions.
By following the tips of #MichaelMahn, I found a solution.
First of all, I draw the silhouette of the visible parts of the selected object in a texture.
And then I use this texture to calculate the outline by checking the neighboring pixels to figure out whether or not I stand on the edge of the silhouette.
outline fragment shader
#version 450
uniform sampler2D silhouette;
in FragData
{
smooth vec2 coords;
} frag;
out vec4 PixelColor;
void main()
{
// if the pixel is black (we are on the silhouette)
if (texture(silhouette, frag.coords).xyz == vec3(0.0f))
{
vec2 size = 1.0f / textureSize(silhouette, 0);
for (int i = -1; i <= +1; i++)
{
for (int j = -1; j <= +1; j++)
{
if (i == 0 && j == 0)
{
continue;
}
vec2 offset = vec2(i, j) * size;
// and if one of the neighboring pixels is white (we are on the border)
if (texture(silhouette, frag.coords + offset).xyz == vec3(1.0f))
{
PixelColor = vec4(vec3(1.0f), 1.0f);
return;
}
}
}
}
discard;
}
paintgl
void paintGL()
{
int w = geometry().width();
int h = geometry().height();
setClearColor(Qt::GlobalColor::darkGray);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawGeometry();
// if we hover a sphere
if (HoveredSphere != RgbFromColorToString(Qt::GlobalColor::black))
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, defaultFramebufferObject());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, addFBO(FBOIndex::SILHOUETTE));
{
// copy depth buffer
GLbitfield mask = GL_DEPTH_BUFFER_BIT;
glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, mask, GL_NEAREST);
// set clear color
setClearColor(Qt::GlobalColor::white);
// enable depth test
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// clear color buffer
glClear(GL_COLOR_BUFFER_BIT);
// draw silhouette
DrawSilhouette(HoveredSphere);
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
// clear depth buffer
glClear(GL_DEPTH_BUFFER_BIT);
// draw outline
DrawOutline();
}
}
PROBLEM :: Now I'd like to parameterize the width of the contour, whose thickness is currently fixed at 1 pixel.
Thank you so much for any suggestion!
Thanks to the advice of #Andrea I found the following solution.
outline fragment shader
#version 450
uniform sampler2D silhouette;
in FragData
{
smooth vec2 coords;
} frag;
out vec4 PixelColor;
void main()
{
// outline thickness
int w = 3;
// if the pixel is black (we are on the silhouette)
if (texture(silhouette, frag.coords).xyz == vec3(0.0f))
{
vec2 size = 1.0f / textureSize(silhouette, 0);
for (int i = -w; i <= +w; i++)
{
for (int j = -w; j <= +w; j++)
{
if (i == 0 && j == 0)
{
continue;
}
vec2 offset = vec2(i, j) * size;
// and if one of the pixel-neighbor is white (we are on the border)
if (texture(silhouette, frag.coords + offset).xyz == vec3(1.0f))
{
PixelColor = vec4(vec3(1.0f), 1.0f);
return;
}
}
}
}
discard;
}
Now I still have a small problem when the selected object is at the edge of the window.
As you can see, the outline is cut sharply.
I tried to "play" with glTexParameter on the parameters GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T.
In the image above you can see the effect I get with
glTexParameters(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameters(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
while in the image below you can see the effect I get with
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &(QVector4D (1.0f, 1.0f, 1.0f, 1.0f)[0]));
glTexParameters(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameters(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
I would like the outline to show up at the edge of the window, but only where necessary.
Thanks a lot!

GLGS: How do I "connect" a sampler to a texture?

I am trying to read from a 3D texture inside a geometry shader:
#version 150
layout(points) in; // origo of cell
layout(points, max_vertices = 1) out;
uniform sampler3D text;
void main (void)
{
for(int i = 0; i < gl_in.length(); ++i)
{
// texture coordinates:
float u, v, w;
// set u, v, and w somehow
...
float value = texture(text, vec3(u, v, w)).r;
bool show;
// set show based on value somehow:
...
if(show) {
gl_Position = gl_in[i].gl_Position;
EmitVertex();
EndPrimitive();
}
}
}
This is how I set up my texure inside my initialize GL code:
int nx = 101;
int ny = 101;
int nz = 101;
float *data = new float[nx*ny*nz];
// set data[] somehow:
...
glEnable(GL_TEXTURE_3D);
glBindTexture(GL_TEXTURE_3D , texture);
glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage3D( GL_TEXTURE_3D,
0, // level-of-detail number. 0 is the base image level.
GL_RED, // internal format
nx, ny, nz,
0, // border
GL_RED, // pixel format
GL_FLOAT, // data type of the pixel data
data);
But how do I associate the sampler "text" inside the geometry shader with my texture?
So far I have not told OpenGL that there is a sampler named "text" and that it shall sample texture.
EDIT: I tried the following:
GLint textLoc = glGetUniformLocation(program, "text");
glUniform1i(textLoc, 0); // sends 0 to "text" in shader
// why do I not just hardcode 0 inside the geometry shader instead ?
glBindTexture(GL_TEXTURE_3D , texture);
glActiveTexture(GL_TEXTURE0); // same as 0 ?
GLuint sampler_state = 0;
glGenSamplers(1, &sampler_state);
glBindSampler(0, sampler_state); // what does this do?
What is wrong here?