首页 > 编程问答 >为什么 SpaceView3D 绘制处理程序不显示我的材质和光线?

为什么 SpaceView3D 绘制处理程序不显示我的材质和光线?

时间:2024-07-26 11:12:50浏览次数:11  
标签:python 3d blender

def draw_callback_px(self, context):
    font_id = 0

    # A4 dimensions at 300 DPI
    a4_width = 707
    a4_height = 1000
    region_width = context.region.width
    region_height = context.region.height

    x_offset = (region_width - a4_width) / 2
    y_offset = (region_height - a4_height) / 2

    draw_a4_outline(context, x_offset, y_offset, a4_width, a4_height)

    font_size = 14
    background_color = (1.0, 1.0, 1.0, 0.8)
    rectangle_height = 3.5 * font_size
    rectangle_width = a4_width - 20

    draw_filled_rectangle(
        x_offset + 10, y_offset + a4_height - 20, rectangle_width, rectangle_height, background_color
    )
    # Rest of drawing code...


class OBJECT_OT_draw_dimensions(Operator):
    bl_idname = "view3d.draw_dimensions"
    bl_label = "Draw Dimensions"
    bl_options = {"REGISTER", "UNDO"}

    _handle = None

    def modal(self, context, event):
        if event.type in {"RIGHTMOUSE", "ESC"} or context.mode != "OBJECT":
            if self._handle is not None:
                bpy.types.SpaceView3D.draw_handler_remove(self._handle, "WINDOW")
                context.area.tag_redraw()
                self._handle = None
            return {"CANCELLED"}
        if event.type in {"TIMER"}:
            context.area.tag_redraw()
        return {"PASS_THROUGH"}

    def invoke(self, context, event):
        if context.area.type == "VIEW_3D":
            if self._handle is None:
                self._handle = bpy.types.SpaceView3D.draw_handler_add(
                    draw_callback_px, (self, context), "WINDOW", "POST_PIXEL"
                )
                context.window_manager.modal_handler_add(self)
                return {"RUNNING_MODAL"}
            else:
                self.report({"WARNING"}, "Dimension drawing is already active")
                return {"CANCELLED"}
        else:
            self.report({"WARNING"}, "View3D not found, cannot run operator")
            return {"CANCELLED"}


class OBJECT_OT_export_to_image(Operator):
    bl_idname = "object.export_to_image"
    bl_label = "Export to Image"
    bl_options = {"REGISTER", "UNDO"}

    fp = fr"my_file_path.JPEG"

    def execute(self, context):
        global to_draw
        to_draw = False

        a4_width = 707
        a4_height = 1000

        framebuffer_image = bpy.data.images.new("buffer_copy", a4_width, a4_height, float_buffer=True, alpha=False, is_data=True)

        def draw():
            global to_draw
            if to_draw:
                framebuffer = gpu.state.active_framebuffer_get()
                viewport_info = gpu.state.viewport_get()
                width = viewport_info[2]
                height = viewport_info[3]
                framebuffer_image.scale(a4_width, a4_height)
                pixelBuffer = framebuffer.read_color(
                    int((width - a4_width) / 2), int((height - a4_height) / 2), a4_width, a4_height, 4, 0, 'FLOAT'
                )
                pixelBuffer.dimensions = a4_width * a4_height * 4
                framebuffer_image.pixels.foreach_set(pixelBuffer)
                framebuffer_image.file_format = 'JPEG'
                framebuffer_image.filepath_raw = self.fp
                try:
                    framebuffer_image.save()
                    self.report({"INFO"}, f"Exported to Image: {self.fp}")
                except Exception as e:
                    self.report({"ERROR"}, f"Failed to save image: {str(e)}")
                to_draw = False

        def update_draw():
            global to_draw
            bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
            to_draw = True
            bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)

        # Ensure the active area is the 3D view for capturing
        for area in context.screen.areas:
            if area.type == "VIEW_3D":
                for region in area.regions:
                    if region.type == "WINDOW":
                        # Draw handler setup for dimensions
                        draw_handler = bpy.types.SpaceView3D.draw_handler_add(draw, (), "WINDOW", "POST_PIXEL")
                        # draw_handler_dimensions = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, (self, context), "WINDOW", "POST_PIXEL")
                        time.sleep(.1)
                        update_draw()

        # Remove the dimensions draw handler after capturing
        bpy.types.SpaceView3D.draw_handler_remove(draw_handler, "WINDOW")
        # bpy.types.SpaceView3D.draw_handler_remove(draw_handler_dimensions, "WINDOW")

        # Delete the created image from bpy.data.images
        bpy.data.images.remove(framebuffer_image)

        return {"FINISHED"}

bpy types SpaceView3D draw_handler_add(draw_callback_px, (self, context), "WINDOW", "POST_PIXEL") 产生:

img produced by script

为什么材质和灯光不显示?对“POST_VIEW”执行相同的操作会显示正确的视图(材质、渲染),但没有线条和矩形。文档仅说明:

通常 POST_PIXEL 用于 2D 绘图, POST_VIEW 用于 3D 绘图。在某些情况下,可以使用 PRE_VIEW BACKDROP 可用于节点编辑器中的背景。 (types.py)

如何设置场景(除了闪电)?它应该是什么样子:

How it should look likee


你遇到的问题是,你正试图在一个不考虑 3D 场景信息(如材质和灯光)的绘图阶段绘制 2D 元素。

以下是分解发生的事情:

  1. POST_PIXEL 绘制处理程序: 当你使用 POST_PIXEL 时,你基本上是在所有 3D 渲染发生 之后 在屏幕空间中进行绘制。这意味着你的 2D 图形(线条、矩形)被绘制在渲染图像的顶部,并且不会受到光照或材质的影响。

  2. POST_VIEW 绘制处理程序: 另一方面, POST_VIEW 允许你在 3D 空间中进行绘制,这意味着你的绘图 受到光照和材质的影响。然而,你遇到的问题是, POST_VIEW 处理程序通常用于 3D 几何图形,而不是 2D 图形。当你尝试在 POST_VIEW 处理程序中绘制 2D 形状时,它们可能会以意外的方式进行渲染,或者根本不进行渲染,因为它们没有与之交互的光照或材质信息。

为了实现你想要的结果(在渲染的 3D 场景之上显示材质、灯光和 2D 图形),你需要结合这两种方法:

  1. POST_VIEW 处理程序中渲染 3D 场景: 这将确保你的场景按预期使用材质和灯光进行渲染。

  2. POST_PIXEL 处理程序中绘制 2D 图形: 这将允许你在渲染的 3D 场景之上绘制 2D 图形。

以下是你可以如何修改你的代码以实现这一点的示例:

import bpy
import gpu
import time

# ... other code ...

def draw_3d_scene(self, context):
    """在 POST_VIEW 处理程序中渲染 3D 场景"""
    # 设置 3D 场景的视图和投影矩阵
    # ...

    # 渲染 3D 场景
    # ...

def draw_2d_graphics(self, context):
    """在 POST_PIXEL 处理程序中绘制 2D 图形"""
    # 你现有的 draw_callback_px 函数的内容
    # ...

class OBJECT_OT_draw_dimensions(Operator):
    # ... (其他代码不变) ...

    def invoke(self, context, event):
        if context.area.type == "VIEW_3D":
            if self._handle is None:
                # 添加 POST_VIEW 处理程序以渲染 3D 场景
                self._handle_3d = bpy.types.SpaceView3D.draw_handler_add(
                    draw_3d_scene, (self, context), "WINDOW", "POST_VIEW"
                )
                # 添加 POST_PIXEL 处理程序以绘制 2D 图形
                self._handle_2d = bpy.types.SpaceView3D.draw_handler_add(
                    draw_2d_graphics, (self, context), "WINDOW", "POST_PIXEL"
                )
                context.window_manager.modal_handler_add(self)
                return {"RUNNING_MODAL"}
            else:
                self.report({"WARNING"}, "Dimension drawing is already active")
                return {"CANCELLED"}
        else:
            self.report({"WARNING"}, "View3D not found, cannot run operator")
            return {"CANCELLED"}

    def modal(self, context, event):
        # ... (其他代码不变) ...

        if event.type in {"RIGHTMOUSE", "ESC"} or context.mode != "OBJECT":
            if self._handle_3d is not None:
                bpy.types.SpaceView3D.draw_handler_remove(self._handle_3d, "WINDOW")
                self._handle_3d = None
            if self._handle_2d is not None:
                bpy.types.SpaceView3D.draw_handler_remove(self._handle_2d, "WINDOW")
                self._handle_2d = None
            context.area.tag_redraw()
            return {"CANCELLED"}
        # ... (其他代码不变) ...

# ... (其他代码不变) ...

通过分别处理 3D 和 2D 绘制,你应该能够在最终渲染中同时获得材质、灯光和 2D 图形。

标签:python,3d,blender
From: 78794697

相关文章

  • python安装第三方库的国内镜像
    直接:pipconfigsetglobal.index-urlhttps://pypi.doubanio.com/simple设置了全局的第三方库的下载文件镜像请求网址。安装第三方库:pipinstallscrapy--scrapy第三方库名称 pip从国内镜像安装的命令使用中国大陆地区的Python包镜像服务时,可以通过修改p......
  • 如何将Python嵌入.Net?
    我尝试基于文档此处和此处使用pythonnet将Python嵌入到.Net中。这是我的代码Runtime.PythonDLL=@"D:\Dev\Console\.conda\python311.dll";PythonEngine.Initialize();dynamicsys=Py.Import("sys");Console.WriteLine("Pythonversion:&quo......
  • 使用pybind11封装c++的dll,供python调用
    用pip安装好pybind11 文件清单,都写在一个目录里//文件名:add.cppextern"C"doubleadd(doublein1,doublein2){returnin1+in2;}//文件名:sub.cppextern"C"doublesub(doublein1,doublein2){returnin1-in2;}//文件名:mul.cppextern"......
  • python-myStudyList
     1  下载软件1.1下载python最新版本并安装下载地址:百度搜索python官网。WelcometoPython.org。 1.2官网学习网页:PythonTutorials–RealPython   1.3也可以下载集成环境软件Anaconda。 Anaconda软件商城官方正版免费下载(msc23.cn) 2 ......
  • Python语法基础
    基本语句输入input() eg:输出print(内容)注释单行注释:#注释内容多行注释:"""注释内容"""数据类型: 字面量:整型、浮点数、字符串......intfloatstring查看数据类型:type(数据)查看数据类型 转换函数int(x):将x转换成整数类型float(x):将x转......
  • PyTesseract 不提取文本?我是所有这些Python的新手,请需要h3lp
    它不想从图像中提取文本,就像终端保持黑色并带有空格,就像它实际上试图提取文本一样,这是我的代码和图像从PIL导入图像导入pytesseract导入CV2“C:\用户\埃米利亚诺\下载\practic.png”pytesseract.pytesseract.tesseract_cmd="C:\ProgramFiles\Tesseract-OCR\tesseract.exe......
  • Python安装第三方库
    Python安装PILPIL(PythonImagingLibrary)是一个旧的Python库,用于处理图像。然而,PIL已经不再维护,并被一个名为Pillow的库所取代。Pillow是PIL的一个分支,并且完全兼容PIL。建议使用Pillow而不是PIL。pipinstallpillowPython安装moviepymoviepy是一个用于视频编辑的Python库,......
  • 优化Python中图像中的OCR文本检测
    我目前正在用python编写一个程序,该程序获取包含大量文本的图像,将其提取到.txt文件,然后将找到的单词与另一个文件中的单词列表进行比较,并创建一些坐标(根据像素)在图像中找到的单词中,如果找到图像,则会在图像中绘制红色方块。到目前为止,我已经正确处理了坐标部分,在单词周围绘制了......
  • Python保存字典类型数据到文件的三种方法
    1、在Python中使用pickle模块的dump函数将字典保存到文件中importpicklemy_dict={'Apple':4,'Banana':2,'Orange':6,'Grapes':11}#保存文件withopen("myDictionary.pkl","wb")astf:pickle.dump(my_dict,tf)......
  • 《最新出炉》系列入门篇-Python+Playwright自动化测试-53- 处理面包屑(详细教程)
    1.简介面包屑(Breadcrumb),又称面包屑导航(BreadcrumbNavigation)这个概念来自童话故事“汉赛尔和格莱特”,当汉赛尔和格莱特穿过森林时,不小心迷路了,但是他们发现沿途走过的地方都撒下了面包屑,让这些面包屑来帮助他们找到回家的路。所以,面包屑导航的作用是告诉访问者他们在网站中......