Wenn Sie ein Add-On für Blender schreiben, möchten Sie hier häufig Bilder verwenden. Ich denke, dort ist. Wenn Sie OpenGL (bgl) von Blender verwenden, können Sie es anzeigen. Probieren Sie es also aus.
Es gibt zwei Möglichkeiten, das Bild zu lesen, also werde ich jede schreiben.
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()
Kopieren Sie es, fügen Sie es in den Texteditor von Blender ein und führen Sie es aus. Geben Sie oben für image_file_path den Pfad des tatsächlich verwendeten Bildes ein.
Ich habe das Blender-Logo entsprechend gezeichnet. Verwenden Sie diese Option, damit das Bild angezeigt wird. Wenn Sie kein passendes Bild haben, verwenden Sie es bitte.
Wenn Sie es ausführen, wird zuerst eine Schaltfläche im Eigenschaftenfenster angezeigt. Drücken Sie also darauf.
Dann
Die Pfadprüfung der zu verwendenden Bilddatei entfällt. Sie sollten es überprüfen, wenn Sie es tatsächlich verwenden.
self.image.gl_load(0, bgl.GL_NEAREST, bgl.GL_NEAREST)
Ich denke, dass die Bilddaten in den Speicher von OpenGL gesendet werden.
Ich denke, die beiden Argumente rechts sind die Speichermethode beim Skalieren.
self.image.bindcode[0]
Die Textur-ID wird hier nach gl_load () eingegeben.
Es war vorher keine Liste, aber aus irgendeinem Grund wurde sie in eine Liste geändert.
Ich weiß nicht, welche Daten außer 0 enthalten sind.
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")
Für diesen Teil wird der Texturspeicher einige Minuten nach seiner Ausführung automatisch freigegeben, sodass die Textur erneut geladen wird. Blender scheint den Speicher von selbst freizugeben.
Der Zeichnungsteil ist derselbe wie OpenGL.
»Es ist sowieso einfach.
gl_load ()
ausführen.Schreiben Sie die GL_Texture-Klasse aus dem obigen Beispiel neu und führen Sie sie aus.
GL_Texturklasse
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)
Hinweis. Es können nur Bitmap-Dateien im 8-Bit-Format geladen werden. Index 0 ist transparent. Es scheint, dass Sie die Bitmap-Datei nicht hochladen können. Bereiten Sie sie daher bitte selbst vor.
Es geht darum, eine Datei zu öffnen, in einem Puffer zu erweitern und in OpenGL zu registrieren.
Wenn Sie in bgl einen Puffer als Argument übergeben möchten, müssen Sie die Buffer-Klasse verwenden. Ich denke, das ist der Unterschied zu gewöhnlichem OpenGL.
Da der Dateiprüfungsprozess weggelassen wird, überprüfen Sie bitte verschiedene Dinge, wenn Sie ihn tatsächlich verwenden.
Persönlich empfehle ich die Verwendung von "bpy.data.images.load ()", da dies immer einfacher ist. Es wird schnell geladen. Die Bilddatei wird auch während der Ausführung in Blender geladen. Selbst wenn Sie sie so speichern, wie sie ist, wird sie nicht gespeichert, wenn die Anzahl der Benutzer 0 beträgt, sodass Sie sich keine Sorgen machen müssen.
Recommended Posts