1
0
forked from Rowland/EG

Initial commit

This commit is contained in:
陈横 2025-08-13 09:30:16 +08:00
commit 4f75cfb1a9
2235 changed files with 330793 additions and 0 deletions

3
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# 默认忽略的文件
/shelf/
/workspace.xml

10
.idea/AugmentWebviewStateStore.xml generated Normal file

File diff suppressed because one or more lines are too long

14
.idea/EG.iml generated Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.10 (eg)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
</module>

View File

@ -0,0 +1,15 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ourVersions">
<value>
<list size="2">
<item index="0" class="java.lang.String" itemvalue="2.7" />
<item index="1" class="java.lang.String" itemvalue="3.14" />
</list>
</value>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.12 (PythonProject)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (eg)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/EG.iml" filepath="$PROJECT_DIR$/.idea/EG.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

4
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"python-envs.pythonProjects": [],
"kiroAgent.configureMCP": "Disabled"
}

View File

@ -0,0 +1,279 @@
# -*- coding: utf-8-*-
"""
Module : Env_Grid_Maker
Author : Saifeddine ALOUI + code from Forklift 's code snippet could be found on panda3D's website
Description :
Creates a 3D implementation of grid that shows axes in 3 possible planes
"""
from panda3d.core import *
from direct.interval.IntervalGlobal import *
class Env_Grid_Maker:
def __init__(self, XYPlaneShow = True, XZPlaneShow = False, YZPlaneShow = False, endCapLinesShow = True, XSize = 50, YSize = 50, ZSize = 50, gridStep = 10, subdiv = 10):
#Create line objects
self.axisLines = LineSegs()
self.gridLines = LineSegs()
self.subdivLines = LineSegs()
#Init passed variables
self.XSize = XSize
self.YSize = YSize
self.ZSize = ZSize
self.gridStep = gridStep
self.subdiv = subdiv
#Init default variables
#Plane and end cap line visibility (1 is show, 0 is hide)
self.XYPlaneShow = XYPlaneShow
self.XZPlaneShow = XZPlaneShow
self.YZPlaneShow = YZPlaneShow
self.endCapLinesShow = endCapLinesShow
#Alpha variables for each plane
#self.XYPlaneAlpha = 1
#self.XZPlaneAlpha = 1
#self.YZPlaneAlpha = 1
#Colors (RGBA passed as a VBase4 object)
self.XAxisColor = VBase4(1, 0, 0, 1)
self.YAxisColor = VBase4(0, 1, 0, 1)
self.ZAxisColor = VBase4(0, 0, 1, 1)
self.gridColor = VBase4(1, 1, 1, 1)
self.subdivColor = VBase4(.35, .35, .35, 1)
#Line thicknesses (in pixels)
self.axisThickness = 3
self.gridThickness = 1
self.subdivThickness = 1
def create(self):
#Set line thicknesses
self.axisLines.setThickness(self.axisThickness)
self.gridLines.setThickness(self.gridThickness)
self.subdivLines.setThickness(self.subdivThickness)
if(self.XSize != 0):
#Draw X axis line
self.axisLines.setColor(self.XAxisColor)
self.axisLines.moveTo(-(self.XSize), 0, 0)
self.axisLines.drawTo(self.XSize, 0, 0)
if(self.YSize != 0):
#Draw Y axis line
self.axisLines.setColor(self.YAxisColor)
self.axisLines.moveTo(0, -(self.YSize), 0)
self.axisLines.drawTo(0, self.YSize, 0)
if(self.ZSize != 0):
#Draw Z axis line
self.axisLines.setColor(self.ZAxisColor)
self.axisLines.moveTo(0, 0, -(self.ZSize))
self.axisLines.drawTo(0, 0, self.ZSize)
#Check to see if primary grid lines should be drawn at all
if(self.gridStep != 0):
#Draw primary grid lines
self.gridLines.setColor(self.gridColor)
#Draw primary grid lines metering x axis if any x-length
if(self.XSize != 0):
if((self.YSize != 0) and (self.XYPlaneShow)):
#Draw y lines across x axis starting from center moving out
#XY Plane
for x in self.myfrange(0, self.XSize, self.gridStep):
self.gridLines.moveTo(x, -(self.YSize), 0)
self.gridLines.drawTo(x, self.YSize, 0)
self.gridLines.moveTo(-x, -(self.YSize), 0)
self.gridLines.drawTo(-x, self.YSize, 0)
if(self.endCapLinesShow):
#Draw endcap lines
self.gridLines.moveTo(self.XSize, -(self.YSize), 0)
self.gridLines.drawTo(self.XSize, self.YSize, 0)
self.gridLines.moveTo(-(self.XSize), -(self.YSize), 0)
self.gridLines.drawTo(-(self.XSize), self.YSize, 0)
if((self.ZSize != 0) and (self.XZPlaneShow)):
#Draw z lines across x axis starting from center moving out
#XZ Plane
for x in self.myfrange(0, self.XSize, self.gridStep):
self.gridLines.moveTo(x, 0, -(self.ZSize))
self.gridLines.drawTo(x, 0, self.ZSize)
self.gridLines.moveTo(-x, 0, -(self.ZSize))
self.gridLines.drawTo(-x, 0, self.ZSize)
if(self.endCapLinesShow):
#Draw endcap lines
self.gridLines.moveTo(self.XSize, 0, -(self.ZSize))
self.gridLines.drawTo(self.XSize, 0, self.ZSize)
self.gridLines.moveTo(-(self.XSize), 0, -(self.ZSize))
self.gridLines.drawTo(-(self.XSize), 0, self.ZSize)
#Draw primary grid lines metering y axis if any y-length
if(self.YSize != 0):
if((self.YSize != 0) and (self.XYPlaneShow)):
#Draw x lines across y axis
#XY Plane
for y in self.myfrange(0, self.YSize, self.gridStep):
self.gridLines.moveTo(-(self.XSize), y, 0)
self.gridLines.drawTo(self.XSize, y, 0)
self.gridLines.moveTo(-(self.XSize), -y, 0)
self.gridLines.drawTo(self.XSize, -y, 0)
if(self.endCapLinesShow):
#Draw endcap lines
self.gridLines.moveTo(-(self.XSize), self.YSize, 0)
self.gridLines.drawTo(self.XSize, self.YSize, 0)
self.gridLines.moveTo(-(self.XSize), -(self.YSize), 0)
self.gridLines.drawTo(self.XSize, -(self.YSize), 0)
if((self.ZSize != 0) and (self.YZPlaneShow)):
#Draw z lines across y axis
#YZ Plane
for y in self.myfrange(0, self.YSize, self.gridStep):
self.gridLines.moveTo(0, y, -(self.ZSize))
self.gridLines.drawTo(0, y, self.ZSize)
self.gridLines.moveTo(0, -y, -(self.ZSize))
self.gridLines.drawTo(0, -y, self.ZSize)
if(self.endCapLinesShow):
#Draw endcap lines
self.gridLines.moveTo(0, self.YSize, -(self.ZSize))
self.gridLines.drawTo(0, self.YSize, self.ZSize)
self.gridLines.moveTo(0, -(self.YSize), -(self.ZSize))
self.gridLines.drawTo(0, -(self.YSize), self.ZSize)
#Draw primary grid lines metering z axis if any z-length
if(self.ZSize != 0):
if((self.XSize != 0) and (self.XZPlaneShow)):
#Draw x lines across z axis
#XZ Plane
for z in self.myfrange(0, self.ZSize, self.gridStep):
self.gridLines.moveTo(-(self.XSize), 0, z)
self.gridLines.drawTo(self.XSize, 0, z)
self.gridLines.moveTo(-(self.XSize), 0, -z)
self.gridLines.drawTo(self.XSize, 0, -z)
if(self.endCapLinesShow):
#Draw endcap lines
self.gridLines.moveTo(-(self.XSize), 0, self.ZSize)
self.gridLines.drawTo(self.XSize, 0, self.ZSize)
self.gridLines.moveTo(-(self.XSize), 0, -(self.ZSize))
self.gridLines.drawTo(self.XSize, 0, -(self.ZSize))
if((self.YSize != 0) and (self.YZPlaneShow)):
#Draw y lines across z axis
#YZ Plane
for z in self.myfrange(0, self.ZSize, self.gridStep):
self.gridLines.moveTo(0, -(self.YSize), z)
self.gridLines.drawTo(0, self.YSize, z)
self.gridLines.moveTo(0, -(self.YSize), -z)
self.gridLines.drawTo(0, self.YSize, -z)
if(self.endCapLinesShow):
#Draw endcap lines
self.gridLines.moveTo(0, -(self.YSize), self.ZSize)
self.gridLines.drawTo(0, self.YSize, self.ZSize)
self.gridLines.moveTo(0, -(self.YSize), -(self.ZSize))
self.gridLines.drawTo(0, self.YSize, -(self.ZSize))
#Check to see if secondary grid lines should be drawn
if(self.subdiv != 0):
#Draw secondary grid lines
self.subdivLines.setColor(self.subdivColor)
if(self.XSize != 0):
adjustedstep = self.gridStep / self.subdiv
if((self.YSize != 0) and (self.XYPlaneShow)):
#Draw y lines across x axis starting from center moving out
#XY
for x in self.myfrange(0, self.XSize, adjustedstep):
self.subdivLines.moveTo(x, -(self.YSize), 0)
self.subdivLines.drawTo(x, self.YSize, 0)
self.subdivLines.moveTo(-x, -(self.YSize), 0)
self.subdivLines.drawTo(-x, self.YSize, 0)
if((self.ZSize != 0) and (self.XZPlaneShow)):
#Draw z lines across x axis starting from center moving out
#XZ
for x in self.myfrange(0, self.XSize, adjustedstep):
self.subdivLines.moveTo(x, 0, -(self.ZSize))
self.subdivLines.drawTo(x, 0, self.ZSize)
self.subdivLines.moveTo(-x, 0, -(self.ZSize))
self.subdivLines.drawTo(-x, 0, self.ZSize)
if(self.YSize != 0):
if((self.YSize != 0) and (self.XYPlaneShow)):
#Draw x lines across y axis
#XY
for y in self.myfrange(0, self.YSize, adjustedstep):
self.subdivLines.moveTo(-(self.XSize), y, 0)
self.subdivLines.drawTo(self.XSize, y, 0)
self.subdivLines.moveTo(-(self.XSize), -y, 0)
self.subdivLines.drawTo(self.XSize, -y, 0)
if((self.ZSize != 0) and (self.YZPlaneShow)):
#Draw z lines across y axis
#YZ
for y in self.myfrange(0, self.YSize, adjustedstep):
self.subdivLines.moveTo(0, y, -(self.ZSize))
self.subdivLines.drawTo(0, y, self.ZSize)
self.subdivLines.moveTo(0, -y, -(self.ZSize))
self.subdivLines.drawTo(0, -y, self.ZSize)
if(self.ZSize != 0):
if((self.XSize != 0) and (self.XZPlaneShow)):
#Draw x lines across z axis
#XZ
for z in self.myfrange(0, self.ZSize, adjustedstep):
self.subdivLines.moveTo(-(self.XSize), 0, z)
self.subdivLines.drawTo(self.XSize, 0, z)
self.subdivLines.moveTo(-(self.XSize), 0, -z)
self.subdivLines.drawTo(self.XSize, 0, -z)
if((self.YSize != 0) and (self.YZPlaneShow)):
#Draw y lines across z axis
#YZ
for z in self.myfrange(0, self.ZSize, adjustedstep):
self.subdivLines.moveTo(0, -(self.YSize), z)
self.subdivLines.drawTo(0, self.YSize, z)
self.subdivLines.moveTo(0, -(self.YSize), -z)
self.subdivLines.drawTo(0, self.YSize, -z)
#Create ThreeAxisGrid nodes and nodepaths
#Create parent node and path
self.parentNode = PandaNode('threeaxisgrid-parentnode')
self.parentNodePath = NodePath(self.parentNode)
#Create axis lines node and path, then reparent
self.axisLinesNode = self.axisLines.create()
self.axisLinesNodePath = NodePath(self.axisLinesNode)
self.axisLinesNodePath.reparentTo(self.parentNodePath)
#Create grid lines node and path, then reparent
self.gridLinesNode = self.gridLines.create()
self.gridLinesNodePath = NodePath(self.gridLinesNode)
self.gridLinesNodePath.reparentTo(self.parentNodePath)
#Create subdivision lines node and path then reparent
self.subdivLinesNode = self.subdivLines.create()
self.subdivLinesNodePath = NodePath(self.subdivLinesNode)
self.subdivLinesNodePath.reparentTo(self.parentNodePath)
return self.parentNodePath
def myfrange(self, start, stop=None, step=None):
if stop is None:
stop = float(start)
start = 0.0
if step is None:
step = 1.0
cur = float(start)
while cur < stop:
yield cur
cur += step

View File

@ -0,0 +1,2 @@
name="QPanda3D"
__all__ = ["Env_Grid_Maker"]

Binary file not shown.

193
QPanda3D/Panda3DWorld.py Normal file
View File

@ -0,0 +1,193 @@
# -*- coding: utf-8-*-
"""
Module : Panda3DWorld
Author : Saifeddine ALOUI
Description :
Inherit this object to create your custom world
"""
import sys
import os
from core.CustomMouseController import CustomMouseController
# 获取 RenderPipelineFile 的路径
render_pipeline_path = './RenderPipelineFile'
# 将该路径添加到 sys.path 中,确保 Python 能够找到它
project_root = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, project_root)
sys.path.insert(0, render_pipeline_path)
# 现在你可以导入 RenderPipelineFile 中的模块了
# 例如,如果你想导入 RenderPipelineFile 中的 RenderPipeline 模块
from RenderPipelineFile.rpcore import RenderPipeline
_global_render_pipeline = None
# PyQt imports
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
# Panda imports
from panda3d.core import *
# from panda3d.core import loadPrcFileData
# loadPrcFileData("", "window-type none") # Set Panda to draw its main window in an offscreen buffer
from direct.showbase.DirectObject import DirectObject
from panda3d.core import GraphicsOutput, Texture, ConfigVariableManager, WindowProperties
# Set up Panda environment
from direct.showbase.ShowBase import ShowBase
import platform
# Local imports
from QPanda3D.QMouseWatcherNode import QMouseWatcherNode
from RenderPipelineFile.rpcore.render_target import RenderTarget
__all__ = ["Panda3DWorld"]
_global_world_instance=None
import builtins
class Panda3DWorld(ShowBase):
"""
Panda3DWorld : A class to handle all panda3D world manipulation
"""
def __init__(self, width=1254, height=729, is_fullscreen=False, size=1.0, clear_color=LVecBase4f(0, 0.5, 0, 1),
name="qpanda3D"):
global _global_world_instance
global _global_render_pipeline
_global_world_instance = self
sort = -100
self.parent = None
# 设置基本配置
loadPrcFileData("", "show-frame-rate-meter 0")
loadPrcFileData("", "window-type offscreen") # 设置为离屏渲染
loadPrcFileData("", f"win-size {width} {height}")
loadPrcFileData("", "win-fixed-size #f") # 允许窗口调整大小
if (is_fullscreen):
loadPrcFileData("", "fullscreen #t")
self.render_pipeline = RenderPipeline()
self.render_pipeline.pre_showbase_init()
ShowBase.__init__(self)
# 初始化渲染管线并设置可调整大小的标志
self.render_pipeline.create(self)
_global_render_pipeline = self.render_pipeline
# 创建 Qt 能读的 RGBA8 贴图
self.qt_output_tex = Texture("qt_output_tex")
self.qt_output_tex.set_format(Texture.F_rgba8)
self.qt_output_tex.set_component_type(Texture.T_unsigned_byte)
# # 获取图形管线对象
# gsg = self.win.getGsg()
# host = gsg.getEngine().getHost()
self.win.add_render_texture(self.qt_output_tex, GraphicsOutput.RTM_copy_ram)
#self.screenTexture = Texture()
#self.screenTexture.setMinfilter(Texture.FTLinear)
#self.screenTexture.setFormat(Texture.FRgba32)
#self.screenTexture.set_wrap_u(Texture.WM_clamp)
#self.screenTexture.set_wrap_v(Texture.WM_clamp)
# buff_size_x = int(self.win.get_x_size() * size)
# buff_size_y = int(self.win.get_y_size() * size)
# winprops = WindowProperties()
# winprops.set_size(buff_size_x, buff_size_y)
#
#
# props = FrameBufferProperties()
# props.set_rgb_color(True)
# props.set_rgba_bits(8, 8, 8, 8)
# props.set_depth_bits(8)
# self.buff = self.graphicsEngine.make_output(
# self.pipe, name, sort,
# props, winprops,
# GraphicsPipe.BF_resizeable,
# self.win.get_gsg(), self.win)
#self.screenTexture = render_pipeline._final_stage.target.color_tex
#self.buff.addRenderTexture(self.screenTexture, GraphicsOutput.RTMCopyRam)
# self.buff.set_sort(sort)
#self.cam = self.makeCamera(self.buff)
#self.render_pipeline._showbase.cam=self.makeCamera(self.buff)
#self.render_pipeline._showbase.cam=self.makeCamera(self.buff)
#self.render_pipeline._showbase.camera.reparentTo(self.render)
#base.camera.reparentTo(self.render)
#self.cam.reparentTo(self.render) # 可选同步
#render_pipeline.set_camera(self.cam)
#添加渲染效果<E69588><E69E9C>
self.cam = self.render_pipeline._showbase.cam
self.camNode = self.cam.node()
self.camLens = self.camNode.get_lens()
self.render_pipeline._showbase.camera = self.render_pipeline._showbase.cam
#self.render_pipeline.daytime_mgr.update()
# if clear_color is None:
# self.buff.set_clear_active(GraphicsOutput.RTPColor, False)
# else:
# self.buff.set_clear_color(clear_color)
# self.buff.set_clear_active(GraphicsOutput.RTPColor, True)
# self.disableMouse()
self.mouse_controller = CustomMouseController(self)
self.mouse_controller.setUp()
def render_pipeline(self):
"""获取 RenderPipeline 实例"""
return self._render_pipeline
def set_parent(self, parent: QWidget):
self.parent = parent
self.mouseWatcherNode = QMouseWatcherNode(parent)
def getAspectRatio(self, win = None):
if win is None and self.parent is not None:
return float(self.parent.width()) / float(self.parent.height())
else:
return super().getAspectRatio(win)
def get_render_pipeline():
"""获取全局 RenderPipeline 单例"""
if _global_render_pipeline is None:
raise RuntimeError(
"RenderPipeline has not been initialized yet. Please create a Panda3DWorld instance first.")
return _global_render_pipeline
def resize_buffer(self, width: int, height: int):
"""根据新窗口尺寸调整 Panda3D 渲染输出尺寸"""
# 设置 Panda3D 的窗口尺寸offscreen 模式下对应输出区域)
props = WindowProperties()
props.set_size(width, height)
self.win.request_properties(props)
# 重新分配输出贴图的大小
self.qt_output_tex.set_x_size(width)
self.qt_output_tex.set_y_size(height)
# 更新 lens 的 aspect ratio
if self.camLens:
self.camLens.set_film_size(width, height) # 或 set_aspect_ratio(width / height)
# 强制更新窗口(有时在 Qt 内嵌时需要)
self.graphicsEngine.open_windows()

View File

@ -0,0 +1,41 @@
# -*- coding: utf-8-*-
"""
Module : QMouseWatcherNode
Author : Niklas Mevenkamp
Description :
This is a MouseWatcherNode implementation that accesses
mouse position and button states through a parent QWidget.
"""
# PyQt imports
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
# Panda imports
from panda3d.core import *
__all__ = ["QMouseWatcherNode"]
class QMouseWatcherNode(MouseWatcher):
def __init__(self, parent):
super().__init__()
self.parent = parent
def getMouse(self, *args, **kwargs):
# map global QCursor pixel position to parent Widget coordinates
pos = self.parent.mapFromGlobal(QCursor.pos())
# map absolute pixel positions to relative ones
rel_x = -1 + 2 * pos.x() / self.parent.width()
rel_y = -1 + 2 * pos.y() / self.parent.height()
# invert y
rel_y = -rel_y
return LPoint2(rel_x, rel_y)
def hasMouse(self):
return isinstance(self.parent, QWidget)

335
QPanda3D/QPanda3DWidget.py Normal file
View File

@ -0,0 +1,335 @@
# -*- coding: utf-8-*-
"""
Module : QPanda3DWidget
Author : Saifeddine ALOUI
Description :
This is the QWidget to be inserted in your standard PyQt5 application.
It takes a Panda3DWorld object at init time.
You should first create the Panda3DWorkd object before creating this widget.
"""
# PyQt imports
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
# Panda imports
from panda3d.core import Texture, WindowProperties, CallbackGraphicsWindow
from panda3d.core import loadPrcFileData
from QPanda3D.QPanda3D_Buttons_Translation import QPanda3D_Button_translation
from QPanda3D.QPanda3D_Keys_Translation import QPanda3D_Key_translation
from QPanda3D.QPanda3D_Modifiers_Translation import QPanda3D_Modifier_translation
__all__ = ["QPanda3DWidget"]
class QPanda3DSynchronizer(QTimer):
def __init__(self, qPanda3DWidget, FPS=60):
QTimer.__init__(self)
self.qPanda3DWidget = qPanda3DWidget
dt = 1000 / FPS
self.setInterval(int(dt))
self.timeout.connect(self.tick)
def tick(self):
taskMgr.step()
self.qPanda3DWidget.update()
def get_panda_key_modifiers(evt):
panda_mods = []
qt_mods = evt.modifiers()
for qt_mod, panda_mod in QPanda3D_Modifier_translation.items():
if (qt_mods & qt_mod) == qt_mod:
panda_mods.append(panda_mod)
return panda_mods
def get_panda_key_modifiers_prefix(evt):
# join all modifiers (except NoModifier, which is None) with '-'
prefix = "-".join([mod for mod in get_panda_key_modifiers(evt) if mod is not None])
# if the prefix is not empty, append a '-'
if prefix:
prefix += '-'
return prefix
class QPanda3DWidget(QWidget):
"""
An interactive panda3D QWidget
Parent : Parent QT Widget
FPS : Number of frames per socond to refresh the screen
debug: Switch printing key events to console on/off
"""
def __init__(self, panda3DWorld, parent=None, FPS=60, debug=False):
QWidget.__init__(self, parent)
self.rp_sync_requested = False
# set fixed geometry
self.panda3DWorld = panda3DWorld
self.panda3DWorld.set_parent(self)
# Setup a timer in Qt that runs taskMgr.step() to simulate Panda's own main loop
# pandaTimer = QTimer(self)
# pandaTimer.timeout.connect()
# pandaTimer.start(0)
self.setFocusPolicy(Qt.StrongFocus)
# Setup another timer that redraws this widget in a specific FPS
# redrawTimer = QTimer(self)
# redrawTimer.timeout.connect(self.update)
# redrawTimer.start(1000/FPS)
self.paintSurface = QPainter()
self.rotate = QTransform()
self.rotate.rotate(180)
self.out_image = QImage()
size = self.panda3DWorld.cam.node().get_lens().get_film_size()
self.initial_film_size = QSizeF(size.x, size.y)
self.initial_size = self.size()
self.synchronizer = QPanda3DSynchronizer(self, FPS)
self.synchronizer.start()
self.debug = debug
def mousePressEvent(self, evt):
button = evt.button()
try:
b = "{}{}".format(get_panda_key_modifiers_prefix(evt), QPanda3D_Button_translation[button])
if self.debug:
print(b)
messenger.send(b,[{"x":evt.x(),"y":evt.y()}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def mouseMoveEvent(self, evt:QtGui.QMouseEvent):
button = evt.button()
try:
b = "mouse-move"
if self.debug:
print(b)
messenger.send(b,[{"x":evt.x(),"y":evt.y()}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def mouseReleaseEvent(self, evt):
button = evt.button()
try:
b = "{}{}-up".format(get_panda_key_modifiers_prefix(evt), QPanda3D_Button_translation[button])
if self.debug:
print(b)
messenger.send(b,[{"x":evt.x(),"y":evt.y()}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def wheelEvent(self, evt):
delta = evt.angleDelta().y()
try:
if self.debug:
print(f"wheel {delta}")
messenger.send('wheel',[{"delta":delta}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def keyPressEvent(self, evt):
key = evt.key()
try:
k = "{}{}".format(get_panda_key_modifiers_prefix(evt), QPanda3D_Key_translation[key])
if self.debug:
print(k)
messenger.send(k)
except:
print("Unimplemented key. Please send an issue on github to fix this problem")
def keyReleaseEvent(self, evt):
key = evt.key()
try:
k = "{}{}-up".format(get_panda_key_modifiers_prefix(evt), QPanda3D_Key_translation[key])
if self.debug:
print(k)
messenger.send(k)
except:
print("Unimplemented key. Please send an issue on github to fix this problem")
def resizeEvent(self, evt):
width = evt.size().width()
height = evt.size().height()
print(f"width:{width}")
print(f"height:{height}")
from Panda3DWorld import resize_buffer
#resize_buffer(width, height)
lens = self.panda3DWorld.cam.node().get_lens()
# lens.set_film_size(self.initial_film_size.width() * evt.size().width() / self.initial_size.width(),
# self.initial_film_size.height() * evt.size().height() / self.initial_size.height())
#self.sync_panda3d_window_size(width, height)
#self.panda3DWorld.buff.setSize(evt.size().width(), evt.size().height())
def minimumSizeHint(self):
return QSize(400, 300)
# Use the paint event to pull the contents of the panda texture to the widget
# def paintEvent(self, event):
# if self.panda3DWorld.screenTexture.mightHaveRamImage():
# tex = self.panda3DWorld.screenTexture
# gsg = base.win.getGsg()
# #self.panda3DWorld.screenTexture.store(gsg)
# base.graphicsEngine.extractTextureData(tex, gsg)
# self.panda3DWorld.screenTexture.setFormat(Texture.FRgba32)
# data = self.panda3DWorld.screenTexture.getRamImage().getData()
# img = QImage(data, self.panda3DWorld.screenTexture.getXSize(), self.panda3DWorld.screenTexture.getYSize(),
# QImage.Format_ARGB32).mirrored()
# self.paintSurface.begin(self)
# self.paintSurface.drawImage(0, 0, img)
# self.paintSurface.end()
# def paintEvent(self, event):
# tex = self.panda3DWorld.qt_output_tex
#
# gsg = base.win.getGsg()
#
#
# if not self.rp_sync_requested:
# base.graphicsEngine.extractTextureData(tex, gsg)
# self.rp_sync_requested = True
# self.update()
# return
#
# if tex.hasRamImage():
# data = tex.getRamImage().getData()
# width = tex.getXSize()
# height = tex.getYSize()
#
# # ✅ 应该 data 长度 = width * height * 4
# img = QImage(data, width, height, QImage.Format_ARGB32).mirrored()
#
# painter = QPainter(self)
# painter.drawImage(0, 0, img)
# painter.end()
#
# self.rp_sync_requested = False
# else:
# print("⚠️ Texture has no RAM image yet, retrying next frame")
# self.rp_sync_requested = False
# self.update()
# def paintEvent(self, event):
# tex = self.panda3DWorld.qt_output_tex
#
# gsg = base.win.getGsg()
#
# if not tex.hasRamImage():
# base.graphicsEngine.extractTextureData(tex, gsg)
# self.update() # 请求下一帧更新
# return
#
# data = tex.getRamImage().getData()
# width = tex.getXSize()
# height = tex.getYSize()
# expected_len = width * height * 4
#
# if len(data) != expected_len:
# print(f"⚠️ 像素数据长度异常({len(data)} != {expected_len}),跳过绘制")
# self.update()
# return
#
# # 一切正常才绘制
# img = QImage(data, width, height, QImage.Format_ARGB32).mirrored()
#
# painter = QPainter(self)
# painter.drawImage(0, 0, img)
# painter.end()
def paintEvent(self, event):
tex = self.panda3DWorld.qt_output_tex
gsg = base.win.getGsg()
if not gsg:
self.update()
return
if not tex.hasRamImage():
base.graphicsEngine.extractTextureData(tex, gsg)
self.update()
return
data = tex.getRamImage().getData()
tex_width = tex.getXSize()
tex_height = tex.getYSize()
expected_len = tex_width * tex_height * 4
if len(data) != expected_len:
print(f"⚠️ 像素数据长度异常({len(data)} != {expected_len}),跳过绘制")
self.update()
return
img = QImage(data, tex_width, tex_height, QImage.Format_ARGB32).mirrored()
widget_width = self.width()
widget_height = self.height()
painter = QPainter(self)
# 【保持宽高比的缩放】
scaled_img = img.scaled(widget_width, widget_height, Qt.KeepAspectRatio, Qt.SmoothTransformation)
# 居中绘制
x_offset = (widget_width - scaled_img.width()) // 2
y_offset = (widget_height - scaled_img.height()) // 2
painter.drawImage(x_offset, y_offset, scaled_img)
painter.end()
def sync_panda3d_window_size(self, width, height):
"""同步 Panda3D 窗口尺寸到 Qt 窗口尺寸"""
try:
from panda3d.core import WindowProperties, LVecBase2i
# 确保尺寸是4的倍数RenderPipeline 要求)
adjusted_width = width - width % 4
adjusted_height = height - height % 4
# 更新窗口属性
props = WindowProperties()
props.setSize(adjusted_width, adjusted_height)
# 对于 offscreen 渲染,直接更新窗口属性
if self.panda3DWorld.win:
self.panda3DWorld.win.request_properties(props)
# 手动触发 RenderPipeline 的尺寸更新逻辑
if hasattr(self.panda3DWorld, 'render_pipeline'):
# 更新全局分辨率
from RenderPipelineFile.rpcore.globals import Globals
Globals.native_resolution = LVecBase2i(adjusted_width, adjusted_height)
# 重新计算渲染分辨率
self.panda3DWorld.render_pipeline._compute_render_resolution()
# 通知各个管理器处理尺寸变化
self.panda3DWorld.render_pipeline.light_mgr.compute_tile_size()
self.panda3DWorld.render_pipeline.stage_mgr.handle_window_resize()
if hasattr(self.panda3DWorld.render_pipeline, 'debugger'):
self.panda3DWorld.render_pipeline.debugger.handle_window_resize()
# 触发插件的窗口尺寸变化钩子
self.panda3DWorld.render_pipeline.plugin_mgr.trigger_hook("window_resized")
print(f"Panda3D 窗口尺寸已同步为: {adjusted_width} x {adjusted_height}")
except Exception as e:
print(f"同步 Panda3D 窗口尺寸失败: {str(e)}")

View File

@ -0,0 +1,52 @@
# -*- coding: utf-8-*-
"""
Module : QPanda3D_Translation_Buttons
Author : Niklas Mevenkamp
Description :
Contains a dictionary that translates QT mouse events to panda3d
mouse events.
"""
# PyQt imports
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
__all__ = ["QPanda3D_Keys_Translation"]
QPanda3D_Button_translation ={
Qt.NoButton:'',
Qt.AllButtons:'unknown',
Qt.LeftButton:'mouse1',
Qt.RightButton:'mouse2',
Qt.MidButton:'mouse3',
Qt.MiddleButton:'mouse3',
Qt.BackButton:'unknown',
Qt.XButton1:'unknown',
Qt.ExtraButton1:'unknown',
Qt.ForwardButton:'unknown',
Qt.XButton2:'unknown',
Qt.ExtraButton2:'unknown',
Qt.TaskButton:'unknown',
Qt.ExtraButton3:'unknown',
Qt.ExtraButton4:'unknown',
Qt.ExtraButton5:'unknown',
Qt.ExtraButton6:'unknown',
Qt.ExtraButton7:'unknown',
Qt.ExtraButton8:'unknown',
Qt.ExtraButton9:'unknown',
Qt.ExtraButton10:'unknown',
Qt.ExtraButton11:'unknown',
Qt.ExtraButton12:'unknown',
Qt.ExtraButton13:'unknown',
Qt.ExtraButton14:'unknown',
Qt.ExtraButton15:'unknown',
Qt.ExtraButton16:'unknown',
Qt.ExtraButton17:'unknown',
Qt.ExtraButton18:'unknown',
Qt.ExtraButton19:'unknown',
Qt.ExtraButton20:'unknown',
Qt.ExtraButton21:'unknown',
Qt.ExtraButton22:'unknown',
Qt.ExtraButton23:'unknown',
Qt.ExtraButton24:'unknown',
}

View File

@ -0,0 +1,486 @@
# -*- coding: utf-8-*-
"""
Module : QPanda3D_Translation_Keys
Author : Saifeddine ALOUI
Description :
Contains a dictionary that translates QT keyboard events to panda3d
keyboard events.
"""
# PyQt imports
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
__all__ = ["QPanda3D_Keys_Translation"]
QPanda3D_Key_translation ={
Qt.Key_0:'0',
Qt.Key_1:'1',
Qt.Key_2:'2',
Qt.Key_3:'3',
Qt.Key_4:'4',
Qt.Key_5:'5',
Qt.Key_6:'6',
Qt.Key_7:'7',
Qt.Key_8:'8',
Qt.Key_9:'9',
Qt.Key_A:'a',
Qt.Key_AE:'ae',
Qt.Key_Aacute:'unknown',
Qt.Key_Acircumflex:'unknown',
Qt.Key_AddFavorite:'unknown',
Qt.Key_Adiaeresis:'unknown',
Qt.Key_Agrave:'unknown',
Qt.Key_Alt:'lalt',
Qt.Key_AltGr:'unknown',
Qt.Key_Ampersand:'unknown',
Qt.Key_Any:'unknown',
Qt.Key_Apostrophe:'unknown',
Qt.Key_ApplicationLeft:'unknown',
Qt.Key_ApplicationRight:'unknown',
Qt.Key_Aring:'unknown',
Qt.Key_AsciiCircum:'unknown',
Qt.Key_AsciiTilde:'unknown',
Qt.Key_Asterisk:'unknown',
Qt.Key_At:'unknown',
Qt.Key_Atilde:'unknown',
Qt.Key_AudioCycleTrack:'unknown',
Qt.Key_AudioForward:'unknown',
Qt.Key_AudioRandomPlay:'unknown',
Qt.Key_AudioRepeat:'unknown',
Qt.Key_AudioRewind:'unknown',
Qt.Key_Away:'unknown',
Qt.Key_B:'b',
Qt.Key_Back:'unknown',
Qt.Key_BackForward:'unknown',
Qt.Key_Backslash:'unknown',
Qt.Key_Backspace:'unknown',
Qt.Key_Backtab:'unknown',
Qt.Key_Bar:'unknown',
Qt.Key_BassBoost:'unknown',
Qt.Key_BassDown:'unknown',
Qt.Key_BassUp:'unknown',
Qt.Key_Battery:'unknown',
Qt.Key_Blue:'unknown',
Qt.Key_Bluetooth:'unknown',
Qt.Key_Book:'unknown',
Qt.Key_BraceLeft:'unknown',
Qt.Key_BraceRight:'unknown',
Qt.Key_BracketLeft:'unknown',
Qt.Key_BracketRight:'unknown',
Qt.Key_BrightnessAdjust:'unknown',
Qt.Key_C:'c',
Qt.Key_CD:'unknown',
Qt.Key_Calculator:'unknown',
Qt.Key_Calendar:'unknown',
Qt.Key_Call:'unknown',
Qt.Key_Camera:'unknown',
Qt.Key_CameraFocus:'unknown',
Qt.Key_Cancel:'unknown',
Qt.Key_CapsLock:'unknown',
Qt.Key_Ccedilla:'unknown',
Qt.Key_ChannelDown:'unknown',
Qt.Key_ChannelUp:'unknown',
Qt.Key_Clear:'unknown',
Qt.Key_ClearGrab:'unknown',
Qt.Key_Close:'unknown',
Qt.Key_Codeinput:'unknown',
Qt.Key_Colon:'unknown',
Qt.Key_Comma:'unknown',
Qt.Key_Community:'unknown',
Qt.Key_Context1:'unknown',
Qt.Key_Context2:'unknown',
Qt.Key_Context3:'unknown',
Qt.Key_Context4:'unknown',
Qt.Key_ContrastAdjust:'unknown',
Qt.Key_Control:'control',
Qt.Key_Copy:'unknown',
Qt.Key_Cut:'unknown',
Qt.Key_D:'d',
Qt.Key_DOS:'unknown',
Qt.Key_Dead_A:'unknown',
Qt.Key_Dead_Abovecomma:'unknown',
Qt.Key_Dead_Abovedot:'unknown',
Qt.Key_Dead_Abovereversedcomma:'unknown',
Qt.Key_Dead_Abovering:'unknown',
Qt.Key_Dead_Aboveverticalline:'unknown',
Qt.Key_Dead_Acute:'unknown',
Qt.Key_Dead_Belowbreve:'unknown',
Qt.Key_Dead_Belowcircumflex:'unknown',
Qt.Key_Dead_Belowcomma:'unknown',
Qt.Key_Dead_Belowdiaeresis:'unknown',
Qt.Key_Dead_Belowdot:'unknown',
Qt.Key_Dead_Belowmacron:'unknown',
Qt.Key_Dead_Belowring:'unknown',
Qt.Key_Dead_Belowtilde:'unknown',
Qt.Key_Dead_Belowverticalline:'unknown',
Qt.Key_Dead_Breve:'unknown',
Qt.Key_Dead_Capital_Schwa:'unknown',
Qt.Key_Dead_Caron:'unknown',
Qt.Key_Dead_Cedilla:'unknown',
Qt.Key_Dead_Circumflex:'unknown',
Qt.Key_Dead_Currency:'unknown',
Qt.Key_Dead_Diaeresis:'unknown',
Qt.Key_Dead_Doubleacute:'unknown',
Qt.Key_Dead_Doublegrave:'unknown',
Qt.Key_Dead_E:'unknown',
Qt.Key_Dead_Grave:'unknown',
Qt.Key_Dead_Greek:'unknown',
Qt.Key_Dead_Hook:'unknown',
Qt.Key_Dead_Horn:'unknown',
Qt.Key_Dead_I:'unknown',
Qt.Key_Dead_Invertedbreve:'unknown',
Qt.Key_Dead_Iota:'unknown',
Qt.Key_Dead_Longsolidusoverlay:'unknown',
Qt.Key_Dead_Lowline:'unknown',
Qt.Key_Dead_Macron:'unknown',
Qt.Key_Dead_O:'unknown',
Qt.Key_Dead_Ogonek:'unknown',
Qt.Key_Dead_Semivoiced_Sound:'unknown',
Qt.Key_Dead_Small_Schwa:'unknown',
Qt.Key_Dead_Stroke:'unknown',
Qt.Key_Dead_Tilde:'unknown',
Qt.Key_Dead_U:'unknown',
Qt.Key_Dead_Voiced_Sound:'unknown',
Qt.Key_Dead_a:'unknown',
Qt.Key_Dead_e:'unknown',
Qt.Key_Dead_i:'unknown',
Qt.Key_Dead_o:'unknown',
Qt.Key_Dead_u:'unknown',
Qt.Key_Delete:'delete',
Qt.Key_Direction_L:'unknown',
Qt.Key_Direction_R:'unknown',
Qt.Key_Display:'unknown',
Qt.Key_Documents:'unknown',
Qt.Key_Dollar:'unknown',
Qt.Key_Down:'arrow_down',
Qt.Key_E:'e',
Qt.Key_ETH:'unknown',
Qt.Key_Eacute:'unknown',
Qt.Key_Ecircumflex:'unknown',
Qt.Key_Ediaeresis:'unknown',
Qt.Key_Egrave:'unknown',
Qt.Key_Eisu_Shift:'unknown',
Qt.Key_Eisu_toggle:'unknown',
Qt.Key_Eject:'unknown',
Qt.Key_End:'unknown',
Qt.Key_Enter:'unknown',
Qt.Key_Equal:'unknown',
Qt.Key_Escape:'escape',
Qt.Key_Excel:'unknown',
Qt.Key_Exclam:'unknown',
Qt.Key_Execute:'unknown',
Qt.Key_Exit:'unknown',
Qt.Key_Explorer:'unknown',
Qt.Key_F:'f',
Qt.Key_F1:'f1',
Qt.Key_F10:'f10',
Qt.Key_F11:'f11',
Qt.Key_F12:'f12',
Qt.Key_F13:'f13',
Qt.Key_F14:'f14',
Qt.Key_F15:'f15',
Qt.Key_F16:'f16',
Qt.Key_F17:'f17',
Qt.Key_F18:'f18',
Qt.Key_F19:'unknown',
Qt.Key_F2:'unknown',
Qt.Key_F20:'unknown',
Qt.Key_F21:'unknown',
Qt.Key_F22:'unknown',
Qt.Key_F23:'unknown',
Qt.Key_F24:'unknown',
Qt.Key_F25:'unknown',
Qt.Key_F26:'unknown',
Qt.Key_F27:'unknown',
Qt.Key_F28:'unknown',
Qt.Key_F29:'unknown',
Qt.Key_F3:'f3',
Qt.Key_F30:'unknown',
Qt.Key_F31:'unknown',
Qt.Key_F32:'unknown',
Qt.Key_F33:'unknown',
Qt.Key_F34:'unknown',
Qt.Key_F35:'unknown',
Qt.Key_F4:'f4',
Qt.Key_F5:'f5',
Qt.Key_F6:'f6',
Qt.Key_F7:'f7',
Qt.Key_F8:'f8',
Qt.Key_F9:'f9',
Qt.Key_Favorites:'unknown',
Qt.Key_Finance:'unknown',
Qt.Key_Find:'unknown',
Qt.Key_Flip:'unknown',
Qt.Key_Forward:'unknown',
Qt.Key_G:'g',
Qt.Key_Game:'unknown',
Qt.Key_Go:'unknown',
Qt.Key_Greater:'unknown',
Qt.Key_Green:'unknown',
Qt.Key_Guide:'unknown',
Qt.Key_H:'h',
Qt.Key_Hangul:'unknown',
Qt.Key_Hangul_Banja:'unknown',
Qt.Key_Hangul_End:'unknown',
Qt.Key_Hangul_Hanja:'unknown',
Qt.Key_Hangul_Jamo:'unknown',
Qt.Key_Hangul_Jeonja:'unknown',
Qt.Key_Hangul_PostHanja:'unknown',
Qt.Key_Hangul_PreHanja:'unknown',
Qt.Key_Hangul_Romaja:'unknown',
Qt.Key_Hangul_Special:'unknown',
Qt.Key_Hangul_Start:'unknown',
Qt.Key_Hangup:'unknown',
Qt.Key_Hankaku:'unknown',
Qt.Key_Help:'unknown',
Qt.Key_Henkan:'unknown',
Qt.Key_Hibernate:'unknown',
Qt.Key_Hiragana:'unknown',
Qt.Key_Hiragana_Katakana:'unknown',
Qt.Key_History:'unknown',
Qt.Key_Home:'home',
Qt.Key_HomePage:'unknown',
Qt.Key_HotLinks:'unknown',
Qt.Key_Hyper_L:'unknown',
Qt.Key_Hyper_R:'unknown',
Qt.Key_I:'i',
Qt.Key_Iacute:'unknown',
Qt.Key_Icircumflex:'unknown',
Qt.Key_Idiaeresis:'unknown',
Qt.Key_Igrave:'unknown',
Qt.Key_Info:'unknown',
Qt.Key_Insert:'unknown',
Qt.Key_J:'j',
Qt.Key_K:'k',
Qt.Key_Kana_Lock:'unknown',
Qt.Key_Kana_Shift:'unknown',
Qt.Key_Kanji:'unknown',
Qt.Key_Katakana:'unknown',
Qt.Key_KeyboardBrightnessDown:'unknown',
Qt.Key_KeyboardBrightnessUp:'unknown',
Qt.Key_KeyboardLightOnOff:'unknown',
Qt.Key_L:'l',
Qt.Key_LastNumberRedial:'unknown',
Qt.Key_Launch0:'unknown',
Qt.Key_Launch1:'unknown',
Qt.Key_Launch2:'unknown',
Qt.Key_Launch3:'unknown',
Qt.Key_Launch4:'unknown',
Qt.Key_Launch5:'unknown',
Qt.Key_Launch6:'unknown',
Qt.Key_Launch7:'unknown',
Qt.Key_Launch8:'unknown',
Qt.Key_Launch9:'unknown',
Qt.Key_LaunchA:'unknown',
Qt.Key_LaunchB:'unknown',
Qt.Key_LaunchC:'unknown',
Qt.Key_LaunchD:'unknown',
Qt.Key_LaunchE:'unknown',
Qt.Key_LaunchF:'unknown',
Qt.Key_LaunchG:'unknown',
Qt.Key_LaunchH:'unknown',
Qt.Key_LaunchMail:'unknown',
Qt.Key_LaunchMedia:'unknown',
Qt.Key_Left:'arrow_left',
Qt.Key_Less:'unknown',
Qt.Key_LightBulb:'unknown',
Qt.Key_LogOff:'unknown',
Qt.Key_M:'m',
Qt.Key_MailForward:'unknown',
Qt.Key_Market:'unknown',
Qt.Key_Massyo:'unknown',
Qt.Key_MediaLast:'unknown',
Qt.Key_MediaNext:'unknown',
Qt.Key_MediaPause:'unknown',
Qt.Key_MediaPlay:'unknown',
Qt.Key_MediaPrevious:'unknown',
Qt.Key_MediaRecord:'unknown',
Qt.Key_MediaStop:'unknown',
Qt.Key_MediaTogglePlayPause:'unknown',
Qt.Key_Meeting:'unknown',
Qt.Key_Memo:'unknown',
Qt.Key_Menu:'unknown',
Qt.Key_MenuKB:'unknown',
Qt.Key_MenuPB:'unknown',
Qt.Key_Messenger:'unknown',
Qt.Key_Meta:'unknown',
Qt.Key_MicMute:'unknown',
Qt.Key_MicVolumeDown:'unknown',
Qt.Key_MicVolumeUp:'unknown',
Qt.Key_Minus:'unknown',
Qt.Key_Mode_switch:'unknown',
Qt.Key_MonBrightnessDown:'unknown',
Qt.Key_MonBrightnessUp:'unknown',
Qt.Key_Muhenkan:'unknown',
Qt.Key_Multi_key:'unknown',
Qt.Key_MultipleCandidate:'unknown',
Qt.Key_Music:'unknown',
Qt.Key_MySites:'unknown',
Qt.Key_N:'n',
Qt.Key_New:'unknown',
Qt.Key_News:'unknown',
Qt.Key_No:'unknown',
Qt.Key_Ntilde:'unknown',
Qt.Key_NumLock:'unknown',
Qt.Key_NumberSign:'unknown',
Qt.Key_O:'o',
Qt.Key_Oacute:'unknown',
Qt.Key_Ocircumflex:'unknown',
Qt.Key_Odiaeresis:'unknown',
Qt.Key_OfficeHome:'unknown',
Qt.Key_Ograve:'unknown',
Qt.Key_Ooblique:'unknown',
Qt.Key_Open:'unknown',
Qt.Key_OpenUrl:'unknown',
Qt.Key_Option:'unknown',
Qt.Key_Otilde:'unknown',
Qt.Key_P:'p',
Qt.Key_PageDown:'unknown',
Qt.Key_PageUp:'unknown',
Qt.Key_ParenLeft:'unknown',
Qt.Key_ParenRight:'unknown',
Qt.Key_Paste:'unknown',
Qt.Key_Pause:'unknown',
Qt.Key_Percent:'unknown',
Qt.Key_Period:'unknown',
Qt.Key_Phone:'unknown',
Qt.Key_Pictures:'unknown',
Qt.Key_Play:'unknown',
Qt.Key_Plus:'unknown',
Qt.Key_PowerDown:'unknown',
Qt.Key_PowerOff:'unknown',
Qt.Key_PreviousCandidate:'unknown',
Qt.Key_Print:'unknown',
Qt.Key_Printer:'unknown',
Qt.Key_Q:'q',
Qt.Key_Question:'unknown',
Qt.Key_QuoteDbl:'unknown',
Qt.Key_QuoteLeft:'unknown',
Qt.Key_R:'r',
Qt.Key_Red:'unknown',
Qt.Key_Redo:'unknown',
Qt.Key_Refresh:'unknown',
Qt.Key_Reload:'unknown',
Qt.Key_Reply:'unknown',
Qt.Key_Return:'unknown',
Qt.Key_Right:'arrow_right',
Qt.Key_Romaji:'unknown',
Qt.Key_RotateWindows:'unknown',
Qt.Key_RotationKB:'unknown',
Qt.Key_RotationPB:'unknown',
Qt.Key_S:'s',
Qt.Key_Save:'unknown',
Qt.Key_ScreenSaver:'unknown',
Qt.Key_ScrollLock:'unknown',
Qt.Key_Search:'unknown',
Qt.Key_Select:'unknown',
Qt.Key_Semicolon:'unknown',
Qt.Key_Send:'unknown',
Qt.Key_Settings:'unknown',
Qt.Key_Shift:'unknown',
Qt.Key_Shop:'unknown',
Qt.Key_SingleCandidate:'unknown',
Qt.Key_Slash:'unknown',
Qt.Key_Sleep:'unknown',
Qt.Key_Space:'space',
Qt.Key_Spell:'unknown',
Qt.Key_SplitScreen:'unknown',
Qt.Key_Standby:'unknown',
Qt.Key_Stop:'unknown',
Qt.Key_Subtitle:'unknown',
Qt.Key_Super_L:'unknown',
Qt.Key_Super_R:'unknown',
Qt.Key_Support:'unknown',
Qt.Key_Suspend:'unknown',
Qt.Key_SysReq:'unknown',
Qt.Key_T:'t',
Qt.Key_THORN:'unknown',
Qt.Key_Tab:'unknown',
Qt.Key_TaskPane:'unknown',
Qt.Key_Terminal:'unknown',
Qt.Key_Time:'unknown',
Qt.Key_ToDoList:'unknown',
Qt.Key_ToggleCallHangup:'unknown',
Qt.Key_Tools:'unknown',
Qt.Key_TopMenu:'unknown',
Qt.Key_TouchpadOff:'unknown',
Qt.Key_TouchpadOn:'unknown',
Qt.Key_TouchpadToggle:'unknown',
Qt.Key_Touroku:'unknown',
Qt.Key_Travel:'unknown',
Qt.Key_TrebleDown:'unknown',
Qt.Key_TrebleUp:'unknown',
Qt.Key_U:'u',
Qt.Key_UWB:'unknown',
Qt.Key_Uacute:'unknown',
Qt.Key_Ucircumflex:'unknown',
Qt.Key_Udiaeresis:'unknown',
Qt.Key_Ugrave:'unknown',
Qt.Key_Underscore:'unknown',
Qt.Key_Undo:'unknown',
Qt.Key_Up:'arrow_up',
Qt.Key_V:'v',
Qt.Key_Video:'unknown',
Qt.Key_View:'unknown',
Qt.Key_VoiceDial:'unknown',
Qt.Key_VolumeDown:'unknown',
Qt.Key_VolumeMute:'unknown',
Qt.Key_VolumeUp:'unknown',
Qt.Key_W:'w',
Qt.Key_WLAN:'unknown',
Qt.Key_WWW:'unknown',
Qt.Key_WakeUp:'unknown',
Qt.Key_WebCam:'unknown',
Qt.Key_Word:'unknown',
Qt.Key_X:'x',
Qt.Key_Xfer:'unknown',
Qt.Key_Y:'y',
Qt.Key_Yacute:'unknown',
Qt.Key_Yellow:'unknown',
Qt.Key_Yes:'unknown',
Qt.Key_Z:'z',
Qt.Key_Zenkaku:'unknown',
Qt.Key_Zenkaku_Hankaku:'unknown',
Qt.Key_Zoom:'unknown',
Qt.Key_ZoomIn:'unknown',
Qt.Key_ZoomOut:'unknown',
Qt.Key_acute:'unknown',
Qt.Key_brokenbar:'unknown',
Qt.Key_cedilla:'unknown',
Qt.Key_cent:'unknown',
Qt.Key_copyright:'unknown',
Qt.Key_currency:'unknown',
Qt.Key_degree:'unknown',
Qt.Key_diaeresis:'unknown',
Qt.Key_division:'unknown',
Qt.Key_exclamdown:'unknown',
Qt.Key_guillemotleft:'unknown',
Qt.Key_guillemotright:'unknown',
Qt.Key_hyphen:'unknown',
Qt.Key_iTouch:'unknown',
Qt.Key_macron:'unknown',
Qt.Key_masculine:'unknown',
Qt.Key_mu:'unknown',
Qt.Key_multiply:'unknown',
Qt.Key_nobreakspace:'unknown',
Qt.Key_notsign:'unknown',
Qt.Key_onehalf:'unknown',
Qt.Key_onequarter:'unknown',
Qt.Key_onesuperior:'unknown',
Qt.Key_ordfeminine:'unknown',
Qt.Key_paragraph:'unknown',
Qt.Key_periodcentered:'unknown',
Qt.Key_plusminus:'unknown',
Qt.Key_questiondown:'unknown',
Qt.Key_registered:'unknown',
Qt.Key_section:'unknown',
Qt.Key_ssharp:'unknown',
Qt.Key_sterling:'unknown',
Qt.Key_threequarters:'unknown',
Qt.Key_threesuperior:'unknown',
Qt.Key_twosuperior:'unknown',
Qt.Key_unknown:'unknown',
Qt.Key_ydiaeresis:'unknown',
Qt.Key_yen:'unknown',
}

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8-*-
"""
Module : QPanda3D_Translation_Modifiers
Author : Niklas Mevenkamp
Description :
Contains a dictionary that translates QT keyboard events to panda3d
keyboard events.
"""
# PyQt imports
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
__all__ = ["QPanda3D_Modifiers_Translation"]
QPanda3D_Modifier_translation ={
Qt.NoModifier:None,
Qt.ShiftModifier:'shift',
Qt.ControlModifier:'control',
Qt.AltModifier:'alt',
Qt.MetaModifier:'unknown',
Qt.KeypadModifier:'unknown',
Qt.GroupSwitchModifier:'unknown',
}

View File

@ -0,0 +1,2 @@
name="QPanda3D"
__all__ = ["generate_qt_to_pd3d_translator"]

Binary file not shown.

View File

@ -0,0 +1,11 @@
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
H=Qt.__dict__
lst = [a for a in H if a.startswith("Key_")]
QPanda3D_Key_translation ="QPanda3D_Key_translation ={"
for i in range(len(lst)):
QPanda3D_Key_translation +="Qt.{}:'unknown',\n".format(lst[i])
QPanda3D_Key_translation += "}"
print(QPanda3D_Key_translation)

2
QPanda3D/__init__.py Normal file
View File

@ -0,0 +1,2 @@
name="QPanda3D"
__all__ = ["QPanda3DWidget", "Panda3DWorld", "QPanda3D_Keys_Translation"]

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

0
README.md Normal file
View File

View File

@ -0,0 +1,4 @@
[flake8]
max-line-length=100
exclude=rplibs/*,data/*,hosek_wilkie_scattering,bake_gi,_DEV,*_generated.py,resources_rc.py

60
RenderPipelineFile/.gitignore vendored Normal file
View File

@ -0,0 +1,60 @@
# --- Ignored extensions ---
*.pyd
*.pyc
*.ignore
*.old
*.egg
*.psd
*.blend1
*.blend2
*.pdb
*.stackdump
*.exr
*.trace
*.autogen*
*.mip
mitsuba.*.log
*.exr
*.txo.pz
# --- Ignored folders and patterns ---
temp/
models/
data/film_grain/*.png
data/default_cubemap/filtered/
_DEV
toolkit/pathtracing_reference/mitsuba/
toolkit/pathtracing_reference/scene*.png
toolkit/pathtracing_reference/Scene*.blend
toolkit/pathtracing_reference/envmap.png
rpplugins/clouds/resources/slices/*
toolkit/rp_distributor/built/
# --- Ignored files ---
TODO.txt
*.flag
desktop.ini
scattering_lut.png
old/
data/gui/loading_screen
data/environment_brdf/scene.png
data/environment_brdf/res/scene.png
toolkit/pathtracing_reference/batch_compare/
toolkit/pathtracing_reference/difference.png
toolkit/pathtracing_reference/res/Scene.blend
toolkit/pathtracing_reference/res/scene.png
toolkit/pathtracing_reference/scene*.png
toolkit/pathtracing_reference/res/tex/envmap.png
_tmp_material.py
*/poisson_disk_generator/source/config_module*
_bake_params*
raw-bake.png
toolkit/bake_gi/resources/*.bam
toolkit/bake_gi/resources/*.blend
toolkit/bake_gi/scene
.vscode

3
RenderPipelineFile/.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# 默认忽略的文件
/shelf/
/workspace.xml

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.10 (RenderPipeline-master) (2)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
</module>

View File

@ -0,0 +1,12 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyStubPackagesAdvertiser" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<list>
<option value="PyQt5-stubs==5.15.6.0" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
RenderPipelineFile/.idea/misc.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (RenderPipeline-master) (2)" project-jdk-type="Python SDK" />
<component name="PythonCompatibilityInspectionAdvertiser">
<option name="version" value="3" />
</component>
</project>

8
RenderPipelineFile/.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/RenderPipeline-master.iml" filepath="$PROJECT_DIR$/.idea/RenderPipeline-master.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,379 @@
[MASTER]
# Specify a configuration file.
#rcfile=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
init-hook=
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS,rplibs,.git,scripts,build.py
# Pickle collected data for later comparisons.
persistent=yes
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
# Use multiple processes to speed up Pylint.
jobs=1
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
extension-pkg-whitelist=
# Allow optimization of some AST trees. This will activate a peephole AST
# optimizer, which will apply various small optimizations. For instance, it can
# be used to obtain the result of joining multiple strings with the addition
# operator. Joining a lot of strings can lead to a maximum recursion error in
# Pylint and this flag can prevent that. It has one side effect, the resulting
# AST will be different than the one from reality.
optimize-ast=yes
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time. See also the "--disable" option for examples.
#enable=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=import-star-module-level,old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating,E0611,W0622,W0201,C0111,R0201,R0913,R0902,R0904,R0914
[REPORTS]
# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html. You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text
# Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]".
files-output=no
# Tells whether to display a full report or only the messages
reports=yes
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
#msg-template=
[BASIC]
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,input,xrange,iteritems,raw_input
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_,x,y,r,g,b,a,uv,w,h,np
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata,tmp,temp
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
# Regular expression matching correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for function names
function-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct variable names
variable-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for variable names
variable-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct constant names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Naming hint for constant names
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression matching correct attribute names
attr-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for attribute names
attr-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct argument names
argument-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for argument names
argument-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct class attribute names
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Naming hint for class attribute names
class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Regular expression matching correct inline iteration names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Naming hint for inline iteration names
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
# Regular expression matching correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$
# Naming hint for class names
class-name-hint=[A-Z_][a-zA-Z0-9]+$
# Regular expression matching correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Naming hint for module names
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression matching correct method names
method-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for method names
method-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
[ELIF]
# Maximum number of nested blocks for function / method body
max-nested-blocks=4
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=100
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,dict-separator
# Maximum number of lines in a module
max-module-lines=1000
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
[LOGGING]
# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=8
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
[SPELLING]
# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no
[TYPECHECK]
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# List of classes names for which member attributes should not be checked
# (useful for classes with attributes dynamically set). This supports can work
# with qualified names.
ignored-classes=
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
[VARIABLES]
# Tells whether we should check for unused import in __init__ files.
init-import=no
# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
dummy-variables-rgx=_$|dummy
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,_cb
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setup,init,load,create
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,_fields,_replace,_source,_make
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=_.*
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of branch for function / method body
max-branches=12
# Maximum number of statements in function / method body
max-statements=50
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of boolean expressions in a if statement
max-bool-expr=5
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,TERMIOS,Bastion,rexec
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception

View File

@ -0,0 +1,18 @@
language: cpp
sudo: required
dist: trusty
compiler: gcc
addons:
apt:
sources:
- sourceline: "deb http://archive.panda3d.org/ubuntu/ trusty-dev main"
packages:
- cmake
- libeigen3-dev
- libfreetype6-dev
- panda3d1.10
script:
- export PYTHONPATH=${PYTHONPATH}:/usr/lib/python2.7/dist-packages
- export PYTHONPATH=${PYTHONPATH}:/usr/share/panda3d
- python2.7 setup.py --ci-build

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -0,0 +1,22 @@
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,70 @@
[![Join the chat at https://gitter.im/tobspr/RenderPipeline](https://badges.gitter.im/tobspr/RenderPipeline.svg)](https://gitter.im/tobspr/RenderPipeline?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/tobspr/RenderPipeline.svg?branch=master)](https://travis-ci.org/tobspr/RenderPipeline)
<!-- # Render Pipeline -->
<img src="http://i.imgur.com/PO4OK4a.png" alt="Deferred Rendering Pipeline with Physically Based Shading" />
Deferred Realtime Rendering Pipeline with Physically Based Shading for the <a href="http://github.com/panda3d/panda3d">Panda3D Game Engine</a>.
### Core Features
- Physically Based Shading
- Deferred Rendering
- Advanced Post-Processing Effects and Framework
- Time of Day System
- Plugin System
## Screenshots
You can click on the images to enlarge them. Besides of that, you can find many more screenshots in my <a href="https://www.dropbox.com/sh/dq4wu3g9jwjqnht/AAABSOPnglDHZYsG5HXR-mhWa" target="_blank">dropbox folder</a>.
**Forest**
<img src="http://i.imgur.com/fD88ZMU.png" />
**Material demo**
<img src="http://i.imgur.com/M5YtvYR.png" />
**Screen space reflections**
<img src="http://i.imgur.com/oOwLXAK.png" />
**Car rendering**
<img src="http://i.imgur.com/hFD4qjV.png" alt="Car rendering" />
**Plugin and Time of Day editor:**
<img src="http://i.imgur.com/a8VpiHS.png" />
**Terrain and volumetric clouds**
<img src="http://i.imgur.com/zE0ywPl.png" />
See the <a target="_blank" href="https://github.com/tobspr/RenderPipeline/wiki/Features">Feature List</a>
for a list of features, and list of techniques I intend to implement.
You can find my todo list for the render pipeline here: <a href="https://trello.com/b/Li2JQi0q/render-pipeline" target="_blank">Render Pipeline Roadmap</a>.
### Getting Started / Wiki
You should checkout the wiki if you want to find out more about the pipeline:
<a target="_blank" href="https://github.com/tobspr/RenderPipeline/wiki">Render Pipeline WIKI</a>
There is also a page about getting started there: <a target="_blank" href="https://github.com/tobspr/RenderPipeline/wiki/Getting%20Started">Getting Started</a>
### Requirements
- OpenGL 4.3 capable GPU (and drivers)
- <a target="_blank" href="https://github.com/panda3d/panda3d">Panda3D</a> Development Build
- 1 GB Graphics Memory recommended *(Can run with less, depends on enabled plugins and resolution)*
**Notice**: It seems that the drivers for Intel HD Graphics on Linux are not
capable of all 4.3 features, so the pipeline is not able to run there!
If you want to use the C++ Modules, checkout <a href="https://github.com/tobspr/RenderPipeline/wiki/Building%20the%20CPP%20Modules" target="_blank">
Building the C++ Modules</a> to get a list of requirements for them.
### Reporting Bugs / Contributing
If you find bugs, or find information missing in the wiki, or want to contribute,
you can find me most of the time in the `#panda3d` channel on freenode.
If I shouldn't be there, feel free to contact me per E-Mail: `tobias.springer1@googlemail.com`

View File

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,30 @@
# This file contains all available debug modes.
# You can add or remove debug modes here, aswell as
# disable or enable them, whatever fits to you.
# NOTICE: This file only has effect if debugging is enabled
# in the pipeline.yaml (settings.pipeline.display_debuger == True)
# Usually you don't have to touch this file, except when developing
# new plugins or adding new features.
render_modes:
- { name: "Shading Model", key: "SHADING_MODEL" }
- { name: "Diffuse", key: "DIFFUSE" }
- { name: "Roughness", key: "ROUGHNESS" }
- { name: "Specular", key: "SPECULAR" }
- { name: "Normal", key: "NORMAL" }
- { name: "Metallic", key: "METALLIC" }
- { name: "Translucency", key: "TRANSLUCENCY" }
- { name: "PSSM Splits", key: "PSSM_SPLITS", requires: "pssm", cxx_only: true }
- { name: "Ambient Occlusion", key: "OCCLUSION", requires: "ao" }
- { name: "Sky AO", key: "SKY_AO", requires: "sky_ao" }
- { name: "Scattering", key: "SCATTERING", requires: "scattering" }
- { name: "Velocity", key: "VELOCITY" }
- { name: "Diffuse Ambient", key: "DIFFUSE_AMBIENT" }
- { name: "Specular Ambient", key: "SPECULAR_AMBIENT" }
- { name: "Luminance", key: "LUMINANCE", special: true }
- { name: "Probe Count", key: "ENVPROBE_COUNT", requires: "env_probes" }
- { name: "Light Count", key: "LIGHT_COUNT" }
- { name: "Light Tiles", key: "LIGHT_TILES", special: true }

View File

@ -0,0 +1,174 @@
# This is the config file used to configure basic settings for Panda3D.
# The pipeline loads it at startup to ensure the environment is setup properly.
# -------------- Development options --------------
pstats-gpu-timing #t
gl-debug #t
gl-debug-object-labels #t
# -------------- Production options ---------------
# pstats-gpu-timing #f
# gl-debug #f
# gl-debug-object-labels #f
# ----------------- Misc Settings -----------------
# Disable V-Sync
sync-video #f
# Limit the pstats-rate. This causes huge lag on windows 10.
pstats-max-rate 200
# No stack trace on assertion, set this to true to make panda crash on assertions
# (which will allow to debug it)
# assert-abort #t
# show-dll-error-dialog #f
# File system should be case sensitive
# NOTICE: Set this to #f if you are using tempfile, since it returns
# wrong cased directory paths
vfs-case-sensitive #t
# Enable state cache, this seems to actually help the performance by a lot
state-cache #t
transform-cache #t
# Hide frame rate meter (we have our own)
show-frame-rate-meter #f
# Set text settings
text-minfilter linear
text-magfilter linear
text-page-size 512 512
text-rwap-mode WM_border_clor
# Better text performance since rdb's patch
text-flatten 0
text-dynamic-merge 1
# For smoother animations
# even-animation #t
# Threading, really buggy!
#threading-model App/Cull/Draw
# Disable stencil, not supported/required
support-stencil #f
framebuffer-stencil #f
# Don't use srgb correction, we do that in the final shader
framebuffer-srgb #f
# Don't use multisamples
framebuffer-multisample #f
multisamples 0
# Don't rescale textures which are no power-of-2
textures-power-2 none
# Set default texture filters
texture-anisotropic-degree 16
texture-magfilter linear
texture-minfilter linear
texture-quality-level fastest
# Enable seamless cubemap filtering, important for environment filtering
gl-cube-map-seamless #t
# Disable caching of textures
model-cache-textures #f
# Disable the annoying SRGB warning from pnmimage
notify-level-pnmimage error
# Disable the buffer viewer, we have our own
show-buffers #f
# Use the default coordinate system, this makes our matrix transformations
# faster because we don't have have to transform them to a different coordinate
# system before
gl-coordinate-system default
# This makes animations smoother, especially if they were exported at 30 FPS
# and are played at 60 FPS
interpolate-frames #t
# Disable workarround in panda which causes our shadow atlas to take twice
# the amount of vram it should, due to an intel driver bug.
gl-force-fbo-color #f
# ----------- OpenGL / Performance Settings ------------
# Require OpenGL 4.3 at least, necessary for Intel drivers on Linux
gl-version 4 3
# Animations on the gpu. The default shader has to get adjusted to support this
# feature before this option can be turned on.
# hardware-animated-vertices #t
# Try this options for performance
# uniquify-matrix #t
# uniquify-transforms #t
# uniquify-states #t
# uniquify-attribs #f
# Enable garbarge collection
garbage-collect-states #t
# garbage-collect-states-rate 0.2
# Compress textures on the drivers?
# driver-compress-textures #t
# Faster animations? (Have to test)
# matrix-palette #t
# display-list-animation #t
# Better GL performance by not using gl-finish and so on
gl-finish #f
gl-force-no-error #t
gl-check-errors #f
gl-force-no-flush #t
gl-force-no-scissor #t
# Eventually disable memory barriers, have to check if this is faster
gl-enable-memory-barriers #f
# Disable threading
lock-to-one-cpu #t
support-threads #f
# Let the driver generate the mipmaps
driver-generate-mipmaps #t
# Use immutable texture storage, it is *supposed* to be faster, but might not be
# XXX: Seems to produce an GL_INVALID_VALUE when disabled
gl-immutable-texture-storage #t
# Default window settings
# depth-bits 0
color-bits 0
framebuffer-depth #f
# Small performance gain by specifying fixed vertex attribute locations.
# Might cause issues with some (incorrectly converted/loaded) meshes though
gl-fixed-vertex-attrib-locations #f
# Disable the fragment shader performance warning
gl-validate-shaders #f
gl-skip-shader-recompilation-warnings #t
alpha-scale-via-texture #f
pstats-name Render Pipeline Stats
rescale-normals #f
screenshot-extension png
# Required for correct velocity
always-store-prev-transform #t
allow-incomplete-render #t
no-singular-invert #f

View File

@ -0,0 +1,84 @@
# This file stores internal settings of the pipeline. It does not contain the
# plugin settings, but just the basic settings of the internal pipeline components.
pipeline:
# This controls whether to show or hide the onscreen debugger. Not showing
# it will also disable the hotkeys, and give a small performance boost.
# Most likely you also don't want to show it in your own game, so set
# it to false in that case.
display_debugger: False
# Affects which debugging information is displayed. If this is set to false,
# only frame time is displayed, otherwise much more information is visible.
# Has no effect when display_debugger is set to false.
advanced_debugging_info: False
# Whether to use the GL_R11F_G11F_B10F texture format to save memory
# and bandwidth. Usually you want to enable this, however it can
# cause banding sometimes, in which case you can disable this setting.
use_r11_g11_b10: false
# Enables to render at a higher or lower resolution than the window size.
# A value of 2.0 for example renders at twice the resolution (supoersampling)
# whereas a value of 0.5 would render at half resolution.
resolution_scale: 1.0
# Whether to render in a special reference mode, which displays the
# environment map as a background, and disable special effects like color
# grading and so on. This is used by the pathtracing reference.
reference_mode: false
# This are the settings affecting the lighting part of the pipeline,
# including builtin shadows and lights.
lighting:
# The pipeline uses clustered deferred shading, this means that the
# screen gets divided into tiles, and for each tile, the lights affecting
# that tile are accumulated. You can adjust the tile size here (in pixels),
# optimal is a tile size which is not too big (to avoid unecessary shading),
# but also not too small (to avoid excessive culling).
culling_grid_size_x: 24
culling_grid_size_y: 16
# The view frustum is additionally divived into slices, to be able to do
# better culling. If you use a higher amount of slices, the culling will
# get more exact, but also more expensive. You have to find the optimal
# size depending on your scene.
culling_grid_slices: 32
# This controls the maximum culling distance in world space. After this
# distance, no lights are rendered anymore. If you choose a lower
# distance, this *can* positively impact performance, but you should not
# set it too low, to avoid getting artifacts.
culling_max_distance: 500.0
# Controls the size of a slice in culling. Lower values might produce
# better performance for less amount of lights, but higher values should
# be used when using many lights, e.g. > 1024, to get better coherency.
culling_slice_width: 2048
# Controls the maximum amount of lights for each cell. If this value
# is set too low, you might get artifacts when having many lights.
# In general, try to set this value as low as possible without getting
# artifacts
max_lights_per_cell: 64
shadows:
# The size of the global shadow atlas, used for point and spot light
# shadows. This should be a power of 2.
atlas_size: 4096
# Maximum of shadow updates which may occur at one time. All updates
# which are beyond that count will get delayed to the next frame.
# If you set this too low, artifacts may occur because of shadows not
# getting updated fast enough. However, this also affects the performance
# quite a bit, since for every shadow map a part of the scene has
# to get re-rendered.
max_updates: 8
# Sets the maximum distance until which shadows are updated. If a shadow
# source is further away, it will no longer recieve updates
max_update_distance: 150.0

View File

@ -0,0 +1,199 @@
# Render Pipeline Plugin Configuration
# Instead of editing this file, prefer to use the Plugin Configurator
# Any formatting and comments will be lost
enabled:
- ao
- bloom
- color_correction
- env_probes
- forward_shading
- motion_blur
- pssm
- scattering
- skin_shading
- sky_ao
- smaa
- ssr
# - clouds
# - dof
# - fxaa
# - volumetrics
# - vxgi
overrides:
ao:
blur_quality: MEDIUM
blur_normal_factor: 2.97
blur_depth_factor: 0.88158
occlusion_strength: 2.19
clip_length: 4
technique: SSAO
ssao_sample_radius: 95.29
ssao_sequence: halton_3D_8
ssao_bias: 0.0143
ssao_max_distance: 7.5
hbao_sample_radius: 255.0
hbao_ray_count: 4
hbao_ray_steps: 3
hbao_tangent_bias: 0.64997
hbao_max_distance: 11.5
ssvo_sequence: halton_2D_8
ssvo_sphere_radius: 18.0
ssvo_max_distance: 3.19
alchemy_sample_radius: 38.86
alchemy_sequence: halton_2D_8
alchemy_max_distance: 5.86
ue4ao_sample_radius: 50.14286
ue4ao_sample_sequence: halton_2D_8
ue4ao_max_distance: 1.47
bloom:
num_mipmaps: 6
bloom_strength: 0.8003
remove_fireflies: False
lens_dirt_factor: 0.0
clouds:
raymarch_steps: 160
color_correction:
tonemap_operator: optimized
reinhard_version: rgb
exponential_factor: 1.23
uc2t_shoulder_strength: 0.3352
uc2t_linear_strength: 0.5339
uc2t_linear_angle: 0.1797
uc2t_toe_strength: 0.3919
uc2t_toe_numerator: 0.0029
uc2t_toe_denumerator: 0.2787
uc2t_reference_white: 10.05
vignette_strength: 0.1286
film_grain_strength: 0.1286
color_lut: film_luts/default_lut.png
use_chromatic_aberration: True
chromatic_aberration_strength: 0.019
chromatic_aberration_samples: 2
manual_camera_parameters: False
min_exposure_value: 0.01
max_exposure_value: 1.0
exposure_scale: 1.0
brightness_adaption_rate: 3.6
darkness_adaption_rate: 0.7
use_sharpen: True
sharpen_strength: 0.5
sharpen_twice: False
dof:
focal_point: 1000.0
focal_size: 994.0
blur_strength: 0.0
near_blur_strength: 0.4286
env_probes:
probe_resolution: 128
diffuse_probe_resolution: 2
max_probes: 16
max_probes_per_cell: 3
forward_shading:
fxaa:
quality: ultra
subpixel_quality: 0.5
edge_threshold: 0.166
min_threshold: 0.833
motion_blur:
num_camera_samples: 6
camera_blur_factor: 0.4
enable_object_blur: False
blur_factor: 0.5
tile_size: 32
max_blur_radius: 10.0
num_samples: 12
pssm:
max_distance: 50.0
logarithmic_factor: 3.0
sun_distance: 100.0
split_count: 4
resolution: 1024
border_bias: 0.058
use_pcf: True
filter_sequence: halton_2D_32
filter_radius: 0.7
fixed_bias: 0.11429
slope_bias: 0.0
normal_bias: 0.67
use_pcss: False
pcss_sequence: halton_2D_16
pcss_penumbra_size: 2.38
pcss_min_penumbra_size: 7.0
use_distant_shadows: True
dist_shadow_resolution: 4096
dist_shadow_clipsize: 400.0
dist_shadow_sundist: 300.0
scene_shadow_resolution: 512
scene_shadow_sundist: 300.0
scattering:
scattering_method: eric_bruneton
ground_reflectance: 0.1231
rayleigh_factor: 0.5
rayleigh_height_scale: 8.0
mie_height_scale: 1.3
mie_phase_factor: 0.3
beta_mie_scattering: 4.0
enable_godrays: False
atmosphere_start: 549.61
skin_shading:
quality: medium
blur_scale: 0.43
sky_ao:
sample_radius: 17.17
max_radius: 500.0
resolution: 1024
sample_sequence: poisson_2D_32
ao_multiplier: 0.83
ao_bias: 0.0
blend_factor: 0.01
capture_height: 568.75
smaa:
use_reprojection: True
smaa_quality: ultra
jitter_pattern: halton8
history_length: 8
jitter_amount: 0.16143
ssr:
effect_scale: 1.0
trace_steps: 64
history_length: 16
abort_on_object_infront: True
intial_bias: 0.1
hit_tolerance: 0.1
roughness_fade: 0.72
skip_invalid_samples: False
border_fade: 0.005
volumetrics:
enable_volumetric_shadows: True
volumetric_shadow_intensity: 8.31
volumetric_shadow_brightness: 1.66
volumetric_shadow_pow: 1.15999
volumetric_max_distance: 79.41429
volumetric_shadow_fadein_distance: 9.49
volumetric_num_steps: 128
vxgi:
grid_resolution: 256
grid_ws_size: 100.0
diffuse_cone_steps: 32
specular_cone_steps: 150

View File

@ -0,0 +1,67 @@
# This file controls the order of all render stages.
# Usually you do not have to modify this, except if you are adding new plugins.
# If you move stages, you should know what you do.
# Commenting out a stage won't disable it, but instead produce an error when
# it is created.
global_stage_order:
# Shadows, Environment and Voxelization
- PSSMShadowStage
- PSSMDistShadowStage
- PSSMSceneShadowStage
- ScatteringEnvmapStage
- SkyAOCaptureStage
- EnvironmentCaptureStage
- VoxelizationStage
# Main scene
- GBufferStage
- ShadowStage
- DownscaleZStage
- CombineVelocityStage
# Light(-culling)
- FlagUsedCellsStage
- CollectUsedCellsStage
- CullLightsStage
- CullProbesStage
# Plugins
- CloudVoxelStage
- AOStage
- SkyAOStage
- ApplyLightsStage
- PSSMStage
- ScatteringStage
- ApplyEnvprobesStage
- VXGIStage
- SSRStage
- AmbientStage
- ForwardStage
- ApplyCloudsStage
- GodrayStage
- VolumetricsStage
- AutoExposureStage
- ManualExposureStage
# Post AA & Effects
- BloomStage
- TonemappingStage
- SMAAStage
- FXAAStage
- DoFStage
- MotionBlurStage
- SkinShadingStage
- SharpenStage
- ColorCorrectionStage
# Finishing stages, do not insert anything below
- UpscaleStage
- FinalStage
- UpdatePreviousPipesStage

View File

@ -0,0 +1,33 @@
# This file controls which tasks are allowed to run each frame.
# Usually you do not have to edit this file, except when developing plugins.
frame_cycles: !!omap
- frame1:
- envprobes_select_and_cull
- pssm_scene_shadows
- frame2:
- envprobes_capture_envmap_face0
- pssm_distant_shadows
- frame3:
- envprobes_capture_envmap_face1
- pssm_convert_distant_to_esm
- frame4:
- envprobes_capture_envmap_face2
- pssm_blur_distant_vert
- frame5:
- pssm_blur_distant_horiz
- envprobes_capture_envmap_face3
- envprobes_capture_envmap_face4
- frame6:
- envprobes_capture_envmap_face5
- scattering_update_envmap
- frame7:
- envprobes_filter_and_store_envmap

View File

@ -0,0 +1,7 @@
material:
name: GroundMaterial
base_color: "../Textures/ground_diffuse.png"
normal: "../Textures/ground_normal.png"
roughness: 0.8
metallic: 0.0
two_sided: true

View File

@ -0,0 +1,16 @@
The skydomes for the skybox were taken from:
Skybox.jpg:
http://www.gravis.com.ua/gal/content/photoprint/sky/sk_21.jpg
Skybox2.jpg:
http://www.artist-reference.com/wp-content/gallery/marlin-studios-gallery/sky-dome-panorma.jpg
I couldn't find a direct license for those photos. If there is one, please contact me.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 985 KiB

View File

@ -0,0 +1,116 @@
#version 430
// Shader to pre-filter the cubemap using importance sampling
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
#define M_PI 3.1415926535897932384626433
vec3 get_transformed_coord(vec2 coord, uint face) {
float f = 1.0;
switch (face) {
case 1: return vec3(-f, coord);
case 2: return vec3(coord, -f);
case 0: return vec3(f, -coord.x, coord.y);
case 3: return vec3(coord.xy * vec2(1, -1), f);
case 4: return vec3(coord.x, f, coord.y);
case 5: return vec3(-coord.x, -f, coord.y);
}
return vec3(0);
}
// From:
// http://www.trentreed.net/blog/physically-based-shading-and-image-based-lighting/
vec2 hammersley(uint i, uint N)
{
return vec2(float(i) / float(N), float(bitfieldReverse(i)) * 2.3283064365386963e-10);
}
// From:
// http://www.gamedev.net/topic/655431-ibl-problem-with-consistency-using-ggx-anisotropy/
vec3 importance_sample_ggx(vec2 xi, float roughness)
{
float r_square = roughness * roughness;
float phi = 2 * M_PI * xi.x;
float cos_theta = sqrt((1 - xi.y) / (1 + (r_square * r_square - 1) * xi.y));
float sin_theta = sqrt(1 - cos_theta * cos_theta);
return vec3(sin_theta * cos(phi), sin_theta * sin(phi), cos_theta);
}
// Converts a normalized spherical coordinate (r = 1) to cartesian coordinates
vec3 spherical_to_vector(float theta, float phi) {
float sin_theta = sin(theta);
return normalize(vec3(
sin_theta * cos(phi),
sin_theta * sin(phi),
cos(theta)
));
}
float brdf_distribution_ggx(float NxH, float roughness) {
float nxh_sq = NxH * NxH;
float tan_sq = (1 - nxh_sq) / nxh_sq;
float f = roughness / max(1e-10, nxh_sq * (roughness * roughness + tan_sq));
return f * f / M_PI;
}
// Finds a tangent and bitangent vector based on a given normal
void find_arbitrary_tangent(vec3 normal, out vec3 tangent, out vec3 bitangent) {
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0, 0, 1) : vec3(0, 1, 0);
tangent = normalize(cross(v0, normal));
bitangent = normalize(cross(tangent, normal));
}
vec3 transform_cubemap_coordinates(vec3 coord) {
return normalize(coord.xyz * vec3(1, -1, 1));
}
uniform samplerCube SourceTex;
uniform int currentSize;
uniform int currentMip;
uniform int currentFace;
layout(rgba16f) uniform imageCube DestTex;
void main() {
ivec2 coord = ivec2(gl_GlobalInvocationID.xy);
vec2 texcoord = vec2(coord + 0.5) / float(currentSize);
texcoord = texcoord * 2.0 - 1.0;
vec3 n = get_transformed_coord(texcoord, currentFace);
n = normalize(n);
n = transform_cubemap_coordinates(n);
float roughness = clamp(float(currentMip) / 7.0, 0.001, 1.0);
// roughness *= roughness;
vec3 tangent, binormal;
find_arbitrary_tangent(n, tangent, binormal);
vec4 accum = vec4(0);
const uint num_samples = 512;
// Ultra high quality, might cause TDR on low-end systems
// const uint num_samples = 4096;
for (uint i = 0; i < num_samples; ++i) {
vec2 xi = hammersley(i, num_samples);
vec3 r = importance_sample_ggx(xi, roughness);
vec3 h = normalize(r.x * tangent + r.y * binormal + r.z * n);
vec3 l = 2.0 * dot(n, h) * h - n;
float NxL = clamp(dot(n, l), 0.0, 1.0);
float NxH = clamp(dot(n, h), 0.0, 1.0);
vec3 sampled = textureLod(SourceTex, l, 0).rgb;
float weight = 1;
weight = clamp(weight, 0.0, 1.0);
accum += vec4(sampled, 1) * weight;
}
accum /= max(0.1, accum.w);
accum.xyz = pow(accum.xyz, vec3(2.2));
imageStore(DestTex, ivec3(coord, currentFace), vec4(accum.xyz, 1.0));
}

View File

@ -0,0 +1,106 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import print_function, division
import os
import shutil
from os.path import dirname, realpath
from panda3d.core import *
from direct.stdpy.file import isdir, isfile, join
from direct.showbase.ShowBase import ShowBase
class Application(ShowBase):
def __init__(self):
load_prc_file_data("", """
textures-power-2 none
window-type offscreen
win-size 100 100
gl-coordinate-system default
notify-level-display error
print-pipe-types #f
gl-version 4 3
""")
ShowBase.__init__(self)
base_path = realpath(dirname(__file__))
os.chdir(base_path)
filter_dir = join(base_path, "tmp/")
if isdir(filter_dir):
shutil.rmtree(filter_dir)
os.makedirs(filter_dir)
source_path = join(base_path, "source")
extension = ".jpg"
if isfile(join(source_path, "1.png")):
extension = ".png"
cubemap = self.loader.loadCubeMap(
Filename.from_os_specific(join(source_path, "#" + extension)))
mipmap, size = -1, 1024
cshader = Shader.load_compute(Shader.SL_GLSL, "filter.compute.glsl")
while size > 1:
size = size // 2
mipmap += 1
print("Filtering mipmap", mipmap)
dest_cubemap = Texture("Dest")
dest_cubemap.setup_cube_map(size, Texture.T_float, Texture.F_rgba16)
node = NodePath("")
for i in range(6):
node.set_shader(cshader)
node.set_shader_inputs(
SourceTex=cubemap,
DestTex=dest_cubemap,
currentSize=size,
currentMip=mipmap,
currentFace=i)
attr = node.get_attrib(ShaderAttrib)
self.graphicsEngine.dispatch_compute(
( (size + 15) // 16, (size+15) // 16, 1), attr, self.win.gsg)
print(" Extracting data ..")
self.graphicsEngine.extract_texture_data(dest_cubemap, self.win.gsg)
print(" Writing data ..")
dest_cubemap.write(join(filter_dir, "{}-#.png".format(mipmap)), 0, 0, True, False)
print("Reading in data back in ..")
tex = self.loader.loadCubeMap(Filename.from_os_specific(join(base_path, "tmp/#-#.png")), readMipmaps="True")
print("Writing txo ..")
tex.write("cubemap.txo.pz")
shutil.rmtree(join(base_path, "tmp"))
Application()

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 735 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 KiB

View File

@ -0,0 +1,7 @@
### Empty textures
This are the empty textures you can use in your models in case you don't have
a detailmap for example.
See the wiki for further information.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,120 @@
"""
Uses mitsuba to generate the environment brdf
"""
from __future__ import print_function
import os
import sys
import math
from panda3d.core import PNMImage, load_prc_file_data, Vec3
load_prc_file_data("", "notify-level error")
load_prc_file_data("", "notify-level-pnmimage error")
configs = {
"normal": {
"out_dir": "slices",
"out_name": "env_brdf_{}.png",
"template_suffix": "",
"sequence": xrange(7),
"samples": 32,
},
"metallic": {
"out_dir": "slices_metal",
"out_name": "env_brdf.png",
"template_suffix": "-metal",
"sequence": [1],
"samples": 32,
},
"clearcoat": {
"out_dir": "slices_coat",
"out_name": "env_brdf.png",
"template_suffix": "-coat",
"sequence": [1],
"samples": 2048,
}
}
# configs_to_run = ["normal", "metallic", "clearcoat"]
configs_to_run = ["clearcoat"]
for config_name in configs_to_run:
config = configs[config_name]
if not os.path.isdir(config["out_dir"]):
os.makedirs(config["out_dir"])
for pass_index in config["sequence"]:
ior = 1.01 + 0.2 * pass_index
dest_size = 512
dest_h = 32
dest = PNMImage(dest_size, dest_h)
# run mitsuba
print("Running mitsuba for ior =", ior, "( index =", pass_index,")")
with open("res/scene" + config["template_suffix"] + ".templ.xml", "r") as handle:
content = handle.read()
content = content.replace("%IOR%", str(ior))
content = content.replace("%SAMPLES%", str(config["samples"]))
with open("res/scene.xml", "w") as handle:
handle.write(content)
os.system("run_mitsuba.bat")
img = PNMImage("scene.png")
source_w = img.get_x_size()
print("Converting ..")
indices = []
nxv_values = []
# Generate nonlinear NxV sequence
for i in xrange(source_w):
v = 1 - i / float(source_w)
NxV = math.sqrt(1 - v*v)
nxv_values.append(NxV)
# Generate lerp indices and weights
for x in xrange(dest_size):
NxV = (x) / float(dest_size)
index = 0
for i, s_nxv in enumerate(reversed(nxv_values)):
if NxV >= s_nxv:
index = i
break
index = len(nxv_values) - index - 1
next_index = index + 1 if index < dest_size - 1 else index
curr_nxv = nxv_values[index]
next_nxv = nxv_values[next_index]
lerp_factor = (NxV - curr_nxv) / max(1e-10, abs(next_nxv - curr_nxv))
lerp_factor = max(0.0, min(1.0, lerp_factor))
indices.append((index, next_index, lerp_factor))
# Generate the final linear lut using the lerp weights
for y in xrange(dest_h):
for x in xrange(dest_size):
curr_i, next_i, lerp = indices[x]
curr_v = img.get_xel(curr_i, y)
next_v = img.get_xel(next_i, y)
dest.set_xel(x, y, curr_v * (1 - lerp) + next_v * lerp)
out_name = config["out_name"].replace("{}", str(pass_index))
dest.write(config["out_dir"] + "/" + out_name)
try:
os.remove("scene.png")
except:
pass

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -0,0 +1,68 @@
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughcoating">
<string name="distribution" value="ggx" />
<rgb name="specularReflectance" value="0, 1, 0" />
<float name="alpha" value="0.0001" />
<float name="thickness" value="5.0" />
<float name="intIOR" value="1.51" />
<bsdf type="roughconductor">
<rgb name="specularReflectance" value="1, 0, 0" />
<string name="material" value="none"/>
<!-- <string name="distribution" value="ggx"/> -->
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
<!-- <float name="alpha" value="0.5" /> -->
</bsdf>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="%SAMPLES%" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>

View File

@ -0,0 +1,56 @@
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughconductor">
<string name="material" value="Ag"/>
<string name="distribution" value="ggx"/>
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="%SAMPLES%" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>

View File

@ -0,0 +1,62 @@
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughplastic">
<!-- <string name="material" value="Cu"/> -->
<string name="distribution" value="ggx"/>
<rgb name="diffuseReflectance" value="0,1,0" />
<rgb name="specularReflectance" value="1,0,0" />
<float name="intIOR" value="%IOR%"/>
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="%SAMPLES%" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>

View File

@ -0,0 +1,68 @@
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughcoating">
<string name="distribution" value="ggx" />
<rgb name="specularReflectance" value="0, 1, 0" />
<float name="alpha" value="0.0001" />
<float name="thickness" value="5.0" />
<float name="intIOR" value="1.51" />
<bsdf type="roughconductor">
<rgb name="specularReflectance" value="1, 0, 0" />
<string name="material" value="none"/>
<!-- <string name="distribution" value="ggx"/> -->
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
<!-- <float name="alpha" value="0.5" /> -->
</bsdf>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="2048" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>

View File

@ -0,0 +1,10 @@
@echo off
"C:/mitsuba/mitsuba" -p 6 res/scene.xml
echo ""
echo Rendering done
echo ""
echo ""
echo ""
"C:/mitsuba/mtsutil" tonemap -g 2.0 res/scene.exr
copy res\scene.png scene.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Some files were not shown because too many files have changed in this diff Show More