У меня есть текстура с прозрачными частями, вместо того, чтобы быть прозрачными, они черные.
Чтобы проверить, правильно ли значения RGBA передаются шейдеру, я сделал все рендеринг в оттенках серого. И, как я думал, альфа-значения не передаются правильно.
В любом случае, вот как загружаются текстуры:
@classmethod
def load_texture(cls, file_name: str):
try:
img = Image.open(f"{sys.path[0]}/res/{file_name}.png").convert('RGBA')
img = img.transpose(Image.FLIP_TOP_BOTTOM) # flip image upside down
except Exception as e:
print(e)
img = Image.open(f"{sys.path[0]}/res/missing_texture.png").convert('RGBA')
img = img.transpose(Image.FLIP_TOP_BOTTOM) # flip image upside down
ix, iy, image = img.size[0], img.size[1], img.tobytes("raw", "RGBA", 0, -1)
texture_id = glGenTextures(1) # generate a texture ID
cls.__textures.append(texture_id)
glBindTexture(GL_TEXTURE_2D, texture_id) # make it current
# copy the texture into the current texture texture_id
glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
return texture_id
А это мой фрагментный шейдер (закомментированная часть явно не работает):
#version 400 core
in vec2 pass_texture_coords;
in vec3 surface_normal;
in vec3 to_light_vector;
in vec3 to_camera_vector;
out vec4 out_color;
uniform sampler2D model_texture;
uniform vec3 light_color;
uniform float shine_damper;
uniform float reflectivity;
void main(void){
vec4 texture_color = texture(model_texture, pass_texture_coords);
texture_color = vec4(vec3(texture_color.a), 1.0);
//if (texture_color.a < 0.5){
// discard;
//}
vec3 unit_normal = normalize(surface_normal);
vec3 unit_light_vector = normalize(to_light_vector);
float n_dot1 = dot(unit_normal, unit_light_vector);
float brightness = max(n_dot1, 0.1);
vec3 diffuse = brightness * light_color;
vec3 unit_vector_to_camera = normalize(to_camera_vector);
vec3 light_direction = -unit_light_vector;
vec3 reflected_light_direction = reflect(light_direction, unit_normal);
float specular_factor = dot(reflected_light_direction, unit_vector_to_camera);
specular_factor = max(specular_factor, 0.0);
float damped_factor = pow(specular_factor, shine_damper);
vec3 final_specular = damped_factor * reflectivity * light_color;
out_color = vec4(diffuse, 1.0) * texture_color + vec4(final_specular, 1.0);
}
Также перед рендерингом чего-либо вызывается этот метод:
@staticmethod
def update_display():
InputController().apply_input() # apply inputs every frame
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) # so that transparent bits of the texture won't get rendered
glEnable(GL_ALPHA_TEST)
glEnable(GL_DEPTH_TEST)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Remove everything from screen (i.e. displays all white)
glClearColor(0, 0.3, 0, 1) # set backdrop color
glLoadIdentity() # Reset all graphic/shape's position
https://registry.khronos.org/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml:
glTexImage2D(
GL_TEXTURE_2D, //target
0, //level
3, //internalformat -> 3 -> GL_RGB -> no alpha
//framebuffer does not necessarily need an alpha channel
//but if you want transparent textures you have to specify one,
//e.g. GL_RGBA (or any other format from Table 2 with alpha)
ix, //width
iy, //height
0, //border, must be 0
GL_RGBA, //format of data
GL_UNSIGNED_BYTE, //type of data
image //data, which gets converted from format to internalformat
//in your case, the alpha components will be discarded
);
Совет: всегда используйте символы, например. GL_XXXX
, устаревший OpenGL принимает числовое значение для internalformat
, но спецификация в приведенной выше ссылке явно предписывает один из символов из таблиц.
Попробую, когда буду дома. Похоже, это исправит ошибку.
Скрещенные пальцы ...
Не решает проблему, вывод остается таким же, как на изображениях.