`
schi
  • 浏览: 205992 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

GPU, Python and Maya

阅读更多
Here an example how to use pyopencl in Maya.

yTwistNodeGPU.py
# --------------------------------------------------------------------------------
# Copyright (c) 2013 Mack Stone. All rights reserved.
# 
# 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.
# --------------------------------------------------------------------------------

"""
Simple deform node use pyopencl in Maya.

@author: Mack Stone
"""

import sys
import logging

import maya.OpenMaya as om
import maya.OpenMayaMPx as ompx
from maya import utils

import numpy
import pyopencl as cl


# opencl code, run on GPU
kernelCode = """
__kernel void ytwist(__global const float4 *pos, 
					__global float4 *newPos, 
                    float angle, 
                    float envelope)
{
	int gid = get_global_id(0);
    
    newPos[gid].xyzw = pos[gid].xyzw;
    
    float ff = angle * pos[gid].y * envelope;
    if(ff != 0.0f)
    {
    	float cct = cos(ff);
        float cst = sin(ff);
        newPos[gid].x = pos[gid].x * cct - pos[gid].z * cst;
        newPos[gid].z = pos[gid].x * cst + pos[gid].z * cct;
    }
}
"""

class YTwistNode(ompx.MPxDeformerNode):
    
    NAME = "yTwistNode"
    ID = om.MTypeId(0x8702)
    
    angle = om.MObject()
    
    def __init__(self):
        ompx.MPxDeformerNode.__init__(self)
        
        # create context
        self._ctx = cl.create_some_context()
        # command queue
        self._queue = cl.CommandQueue(self._ctx)
        # create and build GPU program
        self._program = cl.Program(self._ctx, kernelCode).build()
        
        # setup logger
        formatter = logging.Formatter("%(asctime)s - %(message)s")
        utils._guiLogHandler.setFormatter(formatter)
        
	def deform(self, dataBlock, geomIter, matrix, multiIndex):
        logging.info("start deforming")
        
        # get the angle from the datablock
        angleHandle = dataBlock.inputValue( self.angle )
        angleValue = angleHandle.asDouble()
        
        # get the envelope
        envelope = OpenMayaMPx.cvar.MPxDeformerNode_envelope
        envelopeHandle = dataBlock.inputValue( envelope )
        envelopeValue = envelopeHandle.asFloat()
        
        # get all position data
        logging.info("get all position data")
        pos = numpy.zeros((geomIter.count(), 4), dtype=numpy.float32)
        while not geomIter.isDone():
            point = geomIter.position()
            index = geomIter.index()
            
            pos[index, 0] = point.x
			pos[index, 1] = point.y
            pos[index, 2] = point.z
            pos[index, 3] = point.w
            geomIter.next()
		
        logging.info("start copy data to GPU")
        memf = cl.mem_flags
        # create buffer from pos
        posBuf = cl.Buffer(self._ctx, memf.READ_ONLY | memf.COPY_HOST_PTR, hostbuf=pos)
        # create write buffer
        outBuf = cl.Buffer(self._ctx, memf.WRITE_ONLY, pos.nbytes)
        
        # run GPU Program 
        logging.info("run GPU Program")
        self._program.ytwist(self._queue, pos.shape, None, posBuf, outBuf, 
                             numpy.float32(angleValue), numpy.float32(envelopeValue))
        logging.info("end GPU Program")
        
        # copy data back to memory
        newPos = numpy.zeros_like(pos)
        cl.enqueue_copy(self._queue, newPos, outBuf).wait()
        
        # set positions
        logging.info("set all position")
        geomIter.reset()
        while not geomIter.isDone():
            point = geomIter.position()
            index = geomIter.index()
            
            point.x = float(newPos[index, 0])
            point.y = float(newPos[index, 1])
            point.z = float(newPos[index, 2])
            geomIter.next()
            
		logging.info("end deform")
        
	@staticmethod
    def creator():
        return ompx.asMPxPtr(YTwistNode())
    
    @staticmethod
    def initialize():
        # angle
        nAttr = om.MFnNumericAttribute()
        YTwistNode.angle = nAttr.create("angle", "fa", om.MFnNumericData.kDouble, 0.0)
        nAttr.setKeyable(1)
        
    	# add attribute
        YTwistNode.addAttribute(YTwistNode.angle)
        outputGeom = ompx.cvar.MPxDeformerNode_outputGeom
        YTwistNode.attributeAffects(YTwistNode.angle, outputGeom)
        
# initialize the script plug-in
def initializePlugin(mobject):
    mplugin = ompx.MFnPlugin(mobject)
    try:
        mplugin.registerNode(YTwistNode.NAME, YTwistNode.ID, YTwistNode.creator, 
                             YTwistNode.initialize, ompx.MPxNode.kDeformerNode )
    except:
        sys.stderr.write("Failed to register node: %s\n" % YTwistNode.NAME)

# uninitialize the script plug-in
def uninitializePlugin(mobject):
    mplugin = ompx.MFnPlugin(mobject)
    try:
        mplugin.deregisterNode(YTwistNode.ID)
    except:
        sys.stderr.write("Failed to unregister node: %s\n" % YTwistNode.NAME )


It's slower than yTwistNode.py(CPU) when I test it.
My testing hardware:
CPU: intel Xeon w3530 2.80GHz
Graphics card: nvidia quadro FX 1800

Test on a obj with 960002 vertexes.
GPU: about 18s a time
CPU: about 10s a time

But the slow part is not the GPU computing. It's the while loop. Two while loop take almost 18s.
分享到:
评论

相关推荐

    Python-ExpressiveBodyCapture3DHandsFaceandBodyfromaSingleImage

    为了实现这一目标,开发者可能需要熟悉Python库如TensorFlow、PyTorch等用于构建和训练深度学习模型,OpenCV用于图像处理,以及Blender或Maya等3D建模软件进行模型可视化和后处理。此外,还需要对概率图形模型、优化...

    tw_cloth_solver:Verlet 布料解算器作为 Maya 插件实现

    我将其创建为一个大学测试项目,以探索在基于依赖图的以 VFX 为中心的 DCC 上下文中 GPU 多线程的可能性。 它绝不是经过压力测试的生产就绪解决方案。 其特点包括: 变形器源代码作为 Python 插件屏蔽版本 C++ ...

    ThinkBox Krakatoa MX v2.2.0.51807

    5. **脚本控制**:通过MEL(Maya Embedded Language)或Python,用户可以编写脚本来自动化工作流程,提高效率。 6. **多线程和分布式渲染**:通过分布式渲染技术,Krakatoa MX能够充分利用网络中的多台计算机资源,...

    maya-ml-rivet:机器学习铆钉节点的概念证明

    玛雅毫升铆钉这是通过机器学习完成的Maya铆钉节点的概念证明。 并不意味着是经过优化的代码。 这是Beta版的发行版,您需自行承担风险动机铆钉(通常添加到面部控件)上损失了铆钉上的大部分性能。 因为要使铆钉跟随...

    绘制三维图形并进行旋转

    在实际应用中,我们通常会用到各种工具和库,例如Blender或Maya进行三维建模,Unity或Unreal Engine进行游戏开发,它们内置了丰富的功能来创建和操作三维图形。通过这些工具,你可以轻松地实现以任意轴为中心的旋转...

    数据融合matlab代码-YaoLu.github.io:关于我

    ++,CUDA,OpenCL,MATLAB,Python,TensorFlow,Keras,OpenCV,Numpy,Scipy,Scikit-learn,Pandas,OpenGL,Maya,Unity,Blender等方面具有丰富的动手经验。 项目 分层多视图异构大型3D重建系统(计算机视觉,...

    几款引擎比较BigWorld,Unreal,CryEngine解读.pdf

    它支持无缝世界,使用Python脚本简化开发流程,但仅支持RedHat服务器系统,并且优化难度较大。BigWorld的授权费用相对高昂,一次性购买可能高达200万美元,且核心代码不开放。引擎采用C++开发,使用四叉树进行场景...

    几款引擎比较BigWorld,Unreal,CryEngine解读.docx

    10. **支持工具**:提供服务器负载测试工具,支持DX9,兼容3D MAX和MAYA建模工具。 11. **培训服务**:初期提供3名工程师(1客户端,1服务器,1美术)的现场培训,后期通过MSN进行远程指导。 12. **通信协议**:...

    一个可以转动,含有三片叶片的风车

    1. **图形设计与3D建模**:创建一个可以转动的风车涉及到3D建模技术,比如使用Blender或Maya等软件。每个叶片的颜色不同,这需要对色彩理论和材料应用有深入理解。正弦曲线的应用则可能涉及对物体旋转路径的数学建模...

    blender-3.1.0-alpha-windows.amd64-release.zip

    6. **渲染引擎升级**:Blender内置的Cycles和Eevee渲染引擎可能会有显著改进,如增加新的材质系统、光照模型优化或更快的GPU渲染能力。 7. **动画系统改进**:对于动画师,新的版本可能会提供更好的关键帧编辑工具...

    3D游戏源代码,喜欢3D的可以看看哦

    这包括对GPU和CPU资源的有效利用,比如通过批处理技术减少绘制调用,使用LOD(级别细节)降低复杂度,以及内存管理和多线程优化。 在"GameDemo"这个文件中,很可能包含了上述各种技术的实现。通过研究源代码,你...

    Combustion 4.0.rar

    6. **脚本与自动化**:通过内置的脚本语言或Python接口,用户可以编写脚本来自动化重复任务,定制工作流程,甚至创建全新的工具和插件,极大地提高了工作效率。 7. **实时预览**:Combustion 4.0的一个显著特点是其...

    snow1.zip zwofrdtr

    1. **3D建模**:创建虚拟场景,包括雪地、树木、建筑等元素,可以使用3D建模软件如Blender、Maya或3DS Max来完成。建模时,需要考虑物体的形状、大小、材质,以实现真实感。 2. **纹理映射**:为3D模型添加颜色和...

    游戏开发学习要看的书籍

    - **Python**:用于工具开发和自动化流程,有时也用于游戏逻辑。 3. **数据结构与算法**: - **图形学基础**:理解向量、矩阵、光照、纹理等基本概念。 - **算法应用**:如搜索算法(A*寻路)、图形渲染算法...

    游戏开发游戏开发

    3. **美术资源**:包括3D模型、2D纹理、动画、特效等,这些都是通过专门的软件如Blender、Photoshop、Maya等创建的。 4. **网络编程**:对于多人在线游戏,开发者需要理解网络通信协议,如TCP/IP、UDP,以及处理...

    3DEngine三维动画设计

    - 商业3DEngine如3ds Max、Maya、Houdini等,提供更专业、高级的功能,但可能需要购买许可证。 七、3D动画设计的应用场景 1. 游戏开发:3DEngine是游戏制作的核心,如《绝地求生》、《堡垒之夜》等热门游戏都依赖...

    awesome-ray-tracing:光线跟踪资源的精选列表

    3. **编程语言绑定**:如 Python、C++、JavaScript 等语言的光线跟踪库,便于不同背景的开发者使用。 4. **教程和指南**:针对初学者和进阶者,提供从基础知识到复杂技术的详细教学,如“Learn Ray Tracing in One ...

    Meal_AR

    6. **服务器端开发**:可能涉及后端服务来处理用户数据、提供API接口,或者存储和检索食物信息,这可能使用Node.js、Python的Flask或Django等技术实现。 7. **跨平台兼容**:为了确保在不同设备上都能运行,开发者...

    Monkey-Game

    2. **编程语言**:Unity常用C#,Unreal Engine常用C++,而Cocos2d-x则支持C++或Python等。开发者需要熟悉选定引擎所支持的语言,编写游戏逻辑和交互。 3. **游戏设计**:游戏可能包含关卡设计、角色设定、故事情节...

    studio-crate

    4. **渲染与合成**:对于需要3D建模或特效的工作室,软件如Autodesk Maya、3ds Max或Blender用于创建三维模型和动画。合成软件如Adobe After Effects则用于将2D和3D元素结合在一起,创造出视觉效果。 5. **色彩管理...

Global site tag (gtag.js) - Google Analytics