Lorsque vous écrivez un module complémentaire pour Blender, vous souhaitez souvent utiliser des images ici. Je pense que oui. Si vous utilisez OpenGL (bgl) fourni par Blender, vous pouvez l'afficher, alors essayons-le.
Il y a deux façons de lire l'image, donc j'écrirai chacune.
bpy.data.images.load ()
gl_texture_test.py
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# Blender2.77a
import bpy
import bgl
image_file_path = "C:/Works/blender_rogo.png "
class GL_Texture():
def __init__(self, file_path):
self.image = None
self.width = 0
self.height = 0
self.load_image(file_path)
def load_image(self, file_path):
try:
self.image = bpy.data.images.load(file_path)
except Exception as e:
print(e)
if self.image:
self.width, self.height = self.image.size
self.image.gl_load(0, bgl.GL_NEAREST, bgl.GL_NEAREST)
def remove(self):
if self.image:
try:
self.image.user_clear()
self.image.gl_free()
#self.image.buffers_free()
bpy.data.images.remove(self.image)
except Exception as e:
print(e)
def bind(self):
if self.image.bindcode[0]:
bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.image.bindcode[0])
else:
self.image.gl_load(0, bgl.GL_NEAREST, bgl.GL_NEAREST)
print("reload gl texture")
class GL_Texture_test_Operator(bpy.types.Operator):
bl_idname = "view3d.gl_texture_test_operator"
bl_label = "View3D GL_Texture draw test"
_handle_draw = None
is_enabled = False
_my_texture = None
@staticmethod
def draw_callback_px(self, context):
bgl.glColor4f(1.0, 1.0, 1.0, 1.0)
bgl.glEnable(bgl.GL_BLEND)
bgl.glEnable(bgl.GL_TEXTURE_2D)
tex = GL_Texture_test_Operator._my_texture
w = tex.width
h =tex.height
tex.bind()
bgl.glBegin(bgl.GL_QUADS)
bgl.glTexCoord2f(0.0, 0.0)
bgl.glVertex2f(0.0, 0.0)
bgl.glTexCoord2f(1.0, 0.0)
bgl.glVertex2f(0.0+w, 0.0)
bgl.glTexCoord2f(1.0, 1.0)
bgl.glVertex2f(0.0+w, 0.0+h)
bgl.glTexCoord2f(0.0, 1.0)
bgl.glVertex2f(0.0, 0.0+h)
bgl.glEnd()
bgl.glDisable(bgl.GL_TEXTURE_2D)
bgl.glDisable(bgl.GL_BLEND)
@staticmethod
def handle_add(self, context):
GL_Texture_test_Operator._handle_draw = bpy.types.SpaceView3D.draw_handler_add(
self.draw_callback_px, (self, context), 'WINDOW', 'POST_PIXEL')
@staticmethod
def handle_remove():
if GL_Texture_test_Operator._handle_draw is not None:
bpy.types.SpaceView3D.draw_handler_remove(GL_Texture_test_Operator._handle_draw, 'WINDOW')
GL_Texture_test_Operator._handle_draw = None
GL_Texture_test_Operator.is_enabled = False
@classmethod
def poll(cls, context):
return context.area.type == 'VIEW_3D'
def modal(self, context, event):
if context.area:
context.area.tag_redraw()
return {'PASS_THROUGH'}
def invoke(self, context, event):
if context.area.type == 'VIEW_3D':
if GL_Texture_test_Operator.is_enabled:
self.cancel(context)
return {'FINISHED'}
else:
GL_Texture_test_Operator._my_texture = GL_Texture(image_file_path)
GL_Texture_test_Operator.handle_add(self, context)
GL_Texture_test_Operator.is_enabled = True
context.area.tag_redraw()
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "View3D not found, cannot run operator")
return {'CANCELLED'}
def cancel(self, context):
GL_Texture_test_Operator.handle_remove()
if GL_Texture_test_Operator._my_texture is not None:
GL_Texture_test_Operator._my_texture.remove()
GL_Texture_test_Operator._my_texture = None
class GL_Texture_test_panel(bpy.types.Panel):
bl_label = "GL Texture test"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
def draw(self, context):
layout = self.layout
if GL_Texture_test_Operator.is_enabled:
layout.operator("view3d.gl_texture_test_operator", "Stop", icon="PAUSE")
else:
layout.operator("view3d.gl_texture_test_operator", "Start", icon="PLAY")
def register():
bpy.utils.register_class(GL_Texture_test_Operator)
bpy.utils.register_class(GL_Texture_test_panel)
def unregister():
bpy.utils.unregister_class(GL_Texture_test_panel)
bpy.utils.unregister_class(GL_Texture_test_Operator)
if __name__ == "__main__":
register()
Copiez-le et collez-le dans l'éditeur de texte de Blender et exécutez-le. Pour image_file_path en haut, entrez le chemin de l'image que vous utilisez réellement.
J'ai dessiné le logo Blender de manière appropriée. Utilisez ceci pour que l'image soit affichée. Si vous n'avez pas d'image appropriée, veuillez l'utiliser.
Lorsque vous l'exécutez, un bouton sera d'abord affiché dans le panneau des propriétés, alors appuyez dessus.
Puis
La vérification du chemin du fichier image à utiliser est omise. Vous devriez le vérifier lorsque vous l'utilisez réellement.
self.image.gl_load(0, bgl.GL_NEAREST, bgl.GL_NEAREST)
Je pense que les données d'image sont envoyées à la mémoire d'OpenGL.
Je pense que les deux arguments de droite sont la méthode de stockage lors de la mise à l'échelle.
self.image.bindcode[0]
L'ID de texture est entré ici après gl_load ().
Ce n'était pas une liste avant, mais pour une raison quelconque, elle est devenue une liste.
Je ne sais pas quelles données sont contenues sauf 0.
def bind(self):
if self.image.bindcode[0]:
bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.image.bindcode[0])
else:
self.image.gl_load(0, bgl.GL_NEAREST, bgl.GL_NEAREST)
print("reload gl texture")
Quant à cette partie, la mémoire de texture est automatiquement libérée quelques minutes après son exécution, donc la texture est à nouveau chargée. Blender semble libérer de la mémoire tout seul.
La partie de dessin est la même que OpenGL.
«C'est facile de toute façon.
gl_load ()
.TimeOut
dans OpenGL de l'onglet Système du paramètre utilisateur.
Il semble que si vous le définissez sur 0, il ne sera pas publié, mais il peut être altéré du côté du script, donc s'il disparaît, faisons gl_load ()
.Réécrivez la classe GL_Texture de l'exemple ci-dessus et exécutez-la.
GL_Classe de texture
class GL_Texture():
def __init__(self, file_path):
self.texture_id = 0
self.width = 0
self.height = 0
self.load_8bit_bitmap(file_path)
def load_8bit_bitmap(self, file_path):
f = None
bitmap_data = None
gl_buffer = None
try:
f = open(file_path, 'rb')
file_header = f.read(14)
info_header = f.read(40)
self.width = struct.unpack("<i", info_header[4:8])[0]
self.height = struct.unpack("<i", info_header[8:12])[0]
palette = []
for i in range(256):
rgbr = f.read(4)
palette.append(struct.unpack("BBBB", rgbr)[0:3])
gl_buffer = bgl.Buffer(bgl.GL_BYTE, self.width*self.height*4)
for i in range(self.width*self.height):
data = f.read(1)
index = struct.unpack("B", data)[0]
bgr = palette[index]
gl_buffer[i*4] = bgr[2]
gl_buffer[i*4+1] = bgr[1]
gl_buffer[i*4+2] = bgr[0]
if index == 0:
gl_buffer[i*4+3] = 0
else:
gl_buffer[i*4+3] = 255
f.close()
except Exception as e:
if f is not None:
f.close()
print(e)
return False
# set opengl
textures = bgl.Buffer(bgl.GL_INT, 1)
bgl.glGenTextures(1, textures)
self.texture_id = textures[0]
bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture_id)
bgl.glPixelStorei(bgl.GL_UNPACK_ALIGNMENT, 4)
bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA,
self.width, self.height, 0, bgl.GL_RGBA,
bgl.GL_UNSIGNED_BYTE, gl_buffer)
bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_NEAREST)
bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_NEAREST)
def remove(self):
if self.texture_id:
textures = bgl.Buffer(bgl.GL_INT, 1)
textures[0] = self.texture_id
bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
bgl.glDeleteTextures(1, textures)
self.texture_id = 0
def bind(self):
bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture_id)
Mise en garde. Seuls les fichiers bitmap au format 8 bits peuvent être chargés. L'index 0 est transparent. Il semble que vous ne puissiez pas télécharger le fichier bitmap, veuillez donc le préparer vous-même.
Il s'agit d'un flux d'ouverture d'un fichier, de son expansion dans un tampon et de son enregistrement dans OpenGL.
Dans bgl, si vous voulez passer un tampon comme argument, vous devez utiliser la classe Buffer. Je pense que c'est la différence avec OpenGL ordinaire.
Le processus de vérification des fichiers étant omis, veuillez vérifier diverses choses lorsque vous l'utilisez réellement.
Personnellement, je recommande d'utiliser bpy.data.images.load ()
car c'est plus facile et plus facile. Il se charge vite.
Le fichier image est également chargé dans Blender pendant l'exécution, mais même si vous l'enregistrez tel quel, il ne sera pas enregistré si le nombre d'utilisateurs est égal à 0, vous n'avez donc pas à vous inquiéter trop.