Today, I have tried to launch an OpenGL code which worked pretty well few months ago. However, now, all my textures appear in black while I am (almost) sure it worked well when I left it (I hope I am wrong!).
There is no problem for the vertices, just the textures.
Here are my vertex and fragment shaders:
VERTEX_SHADER = """
#version 440 core
uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;
in vec2 position;
in vec2 texcoord;
out vec2 Texcoord;
void main()
{
gl_Position = Projection*View*Model*vec4(position, 0.0, 1.0);
Texcoord = texcoord;
}
"""
FRAGMENT_SHADER_WATERFALL = """
#version 440 core
in vec2 Texcoord;
uniform usampler2D texSonar;
uniform sampler2D transcodMap;
out vec4 fragColor;
void main()
{
// retrieve 16-bits value
uint value = texture(texSonar, Texcoord).x;
// find out the corresponding uv coordinates in the colormap
ivec2 uv = ivec2(value % 0x100, value / 0x100);
// apply it
vec4 tmp = texelFetch(transcodMap, uv, 0);
fragColor = vec4(tmp.rgb, 1);
} """
transcodMap is a 256*256 image where each of the 65535 pixels the (R, G, B) color to assign to a given pixel.
My PaintGL method which call the renderWaterfall one:
def paintGL(self):
# Every time the paintGL (or updateGL which call the paintGL one) method is called,
# we need to reload the View matrix to ensure that the right one is taken into
# into account, as the two GL widgets share the same context.
# loc = glGetUniformLocation(self.shaderProgram, 'View')
# glUniformMatrix4fv(loc, 1, False, np.ascontiguousarray(self.matView.T))
# loc = glGetUniformLocation(self.shaderProgram, 'Projection')
# glUniformMatrix4fv(loc, 1, False, np.ascontiguousarray(self.matProj.T))
# print('paintGL CALL from %s'%str(type(self)))
self.viewport = fn.viewport(0, 0, self.width(), self.height())
glUseProgram(self.program.programId())
glClearColor(0, 0, 1, 1)
# to ensure vertices are OK
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
glEnable(GL_DEPTH_TEST)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
if np.array(self.objects).size:
#print('there are %i objects' % (len(self.objects)))
# active shader program
self.objects[0].renderWaterfall(self.program.programId())
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindTexture(GL_TEXTURE_2D, 0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
glUseProgram(0)
if self.boolCursor:
self.updateCursor()
else:
if self.boolCursor:
self.updateCursor()
The renderWaterfall() method consists in iterating over all the tiles to display them:
def renderWaterfall(self, programID):
glActiveTexture(GL_TEXTURE1)
glBindTexture(GL_TEXTURE_2D, self.colormapBuffer)
glUniform1i(glGetUniformLocation(programID, 'transcodMap'), 0)
# only display the first tile for debugging purpose
for i, tile in enumerate(self.tileList[0:1]):
# print('Buffer info: Position: %i | Texcoord: %i | '
# 'Texture: %i | Indices: %i' %(tile.VBO[0], tile.VBO[1], tile.TBO, tile.EBO))
#print(obj.indices)
loc_pos = glGetAttribLocation(programID, "position")
glEnableVertexAttribArray(loc_pos)
glBindBuffer(GL_ARRAY_BUFFER, tile.VBO[0])
glVertexAttribPointer(loc_pos, 2, GL_DOUBLE, False, 0, ctypes.c_void_p(0))
loc_uv = glGetAttribLocation(programID, "texcoord")
glEnableVertexAttribArray(loc_uv)
glBindBuffer(GL_ARRAY_BUFFER, tile.VBO[1])
glVertexAttribPointer(loc_uv, 2, GL_DOUBLE, False, 0, ctypes.c_void_p(0))
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, tile.TBO)
glUniform1i(glGetUniformLocation(programID, 'texSonar'), 0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tile.EBO)
glDrawElements(GL_TRIANGLES, tile.indices.size, GL_UNSIGNED_INT, ctypes.c_void_p(0))
glDisableVertexAttribArray(loc_pos)
glDisableVertexAttribArray(loc_uv)
Before requesting displaying, I (of course) fill my Tile objects. An example is given below, where vertices, uv_coordinates, indices and the texture tile are already computed:
glBindBuffer(GL_ARRAY_BUFFER, tileObj.VBO[0])
glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_DYNAMIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, tileObj.VBO[1])
glBufferData(GL_ARRAY_BUFFER, uv_coordinates.nbytes, uv_coordinates, GL_DYNAMIC_DRAW)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tileObj.EBO)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.nbytes, indices, GL_DYNAMIC_DRAW)
glBindTexture(GL_TEXTURE_2D, tileObj.TBO)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
img_data = np.ascontiguousarray(tile.flatten(), dtype=np.uint16)
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, tile.shape[0], tile.shape[1], 0, GL_RED_INTEGER,
GL_UNSIGNED_SHORT, img_data)
# unbind buffers
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindTexture(GL_TEXTURE_2D, 0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
I do not manage to see what could explain the fact that I am unable to display textures.
EDIT:
I’ve just noticed that removing the following line (which fills the texture buffer):
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, tile.shape[0], tile.shape[1], 0, GL_RED_INTEGER,
GL_UNSIGNED_SHORT, img_data)
has no effect i.e. no error which seems strange…
Moreover, I got an “implicit cast from int to uint” in the fragment shader but I can’t see where.