1 from __future__
import division
14 import maya.api.OpenMaya
as om
15 import maya.api.OpenMayaRender
as omr
25 The presence of this function tells Maya that the plugin produces, and
26 expects to be passed, objects created using the Maya Python API 2.0.
35 def smoothstep(t, a, b):
41 return t*t*(3.0 - 2.0*t)
43 def linearstep(t, a, b):
48 return (t - a)/(b - a)
53 class brickTextureNode(om.MPxNode):
55 id = om.MTypeId( 0x81163 )
69 return brickTextureNode()
73 nAttr = om.MFnNumericAttribute()
77 brickTextureNode.aColor1 = nAttr.createColor(
"brickColor",
"bc")
82 nAttr.default = (.75, .3, .1)
84 brickTextureNode.aColor2 = nAttr.createColor(
"jointColor",
"jc")
89 nAttr.default = (.75, .75, .75)
91 brickTextureNode.aBlurFactor = nAttr.create(
"blurFactor",
"bf", om.MFnNumericData.kFloat)
99 child1 = nAttr.create(
"uCoord",
"u", om.MFnNumericData.kFloat)
100 child2 = nAttr.create( "vCoord",
"v", om.MFnNumericData.kFloat)
101 brickTextureNode.aUVCoord = nAttr.create(
"uvCoord",
"uv", child1, child2)
103 nAttr.storable =
True
104 nAttr.readable =
True
105 nAttr.writable =
True
108 child1 = nAttr.create(
"uvFilterSizeX",
"fsx", om.MFnNumericData.kFloat)
109 child2 = nAttr.create(
"uvFilterSizeY",
"fsy", om.MFnNumericData.kFloat)
110 brickTextureNode.aFilterSize = nAttr.create(
"uvFilterSize",
"fs", child1, child2)
112 nAttr.storable =
True
113 nAttr.readable =
True
114 nAttr.writable =
True
118 brickTextureNode.aOutColor = nAttr.createColor(
"outColor",
"oc")
119 nAttr.keyable =
False
120 nAttr.storable =
False
121 nAttr.readable =
True
122 nAttr.writable =
False
125 om.MPxNode.addAttribute(brickTextureNode.aColor1)
126 om.MPxNode.addAttribute(brickTextureNode.aColor2)
127 om.MPxNode.addAttribute(brickTextureNode.aBlurFactor)
128 om.MPxNode.addAttribute(brickTextureNode.aFilterSize)
129 om.MPxNode.addAttribute(brickTextureNode.aUVCoord)
131 om.MPxNode.addAttribute(brickTextureNode.aOutColor)
134 om.MPxNode.attributeAffects(brickTextureNode.aColor1, brickTextureNode.aOutColor)
135 om.MPxNode.attributeAffects(brickTextureNode.aColor2, brickTextureNode.aOutColor)
136 om.MPxNode.attributeAffects(brickTextureNode.aBlurFactor, brickTextureNode.aOutColor)
137 om.MPxNode.attributeAffects(brickTextureNode.aFilterSize, brickTextureNode.aOutColor)
138 om.MPxNode.attributeAffects(brickTextureNode.aUVCoord, brickTextureNode.aOutColor)
141 om.MPxNode.__init__(self)
152 def compute(self, plug, block):
154 if (plug != brickTextureNode.aOutColor)
and (plug.parent() != brickTextureNode.aOutColor):
157 uv = block.inputValue( brickTextureNode.aUVCoord ).asFloat2()
158 surfaceColor1 = block.inputValue( brickTextureNode.aColor1 ).asFloatVector()
159 surfaceColor2 = block.inputValue( brickTextureNode.aColor2 ).asFloatVector()
162 uv[0] -= math.floor(uv[0])
163 uv[1] -= math.floor(uv[1])
168 blur = block.inputValue( brickTextureNode.aBlurFactor ).asFloat()
171 v2 = v1 + brickHeight
172 v3 = v2 + borderWidth
173 v4 = v3 + brickHeight
176 u3 = u2 + borderWidth
179 fs = block.inputValue( brickTextureNode.aFilterSize ).asFloat2()
183 t = max(min(linearstep(uv[1], v1 - dv, v1 + dv) - linearstep(uv[1], v2 - dv, v2 + dv), max(linearstep(uv[0], u3 - du, u3 + du), 1 - linearstep(uv[0], u2 - du, u2 + du))), min(linearstep(uv[1], v3 - dv, v3 + dv) - linearstep(uv[1], v4 - dv, v4 + dv), linearstep(uv[0], u1 - du, u1 + du) - linearstep(uv[0], u4 - du, u4 + du)))
185 resultColor = t*surfaceColor1 + (1.0 - t)*surfaceColor2
188 outColorHandle = block.outputValue( brickTextureNode.aOutColor )
189 outColorHandle.setMFloatVector( resultColor )
190 outColorHandle.setClean()
195 def postConstructor(self):
201 class brickTextureNodeOverride(omr.MPxShadingNodeOverride):
204 return brickTextureNodeOverride(obj)
206 def __init__(self, obj):
207 omr.MPxShadingNodeOverride.__init__(self, obj)
210 fragmentMgr = omr.MRenderer.getFragmentManager()
211 if fragmentMgr !=
None:
212 if not fragmentMgr.hasFragment(
"brickTextureNodePluginFragment"):
213 fragmentBody =
"<fragment uiName=\"brickTextureNodePluginFragment\" name=\"brickTextureNodePluginFragment\" type=\"plumbing\" class=\"ShadeFragment\" version=\"1.0\">"
214 fragmentBody +=
" <description><![CDATA[Brick procedural texture fragment]]></description>"
215 fragmentBody +=
" <properties>"
216 fragmentBody +=
" <float3 name=\"brickColor\" />"
217 fragmentBody +=
" <float3 name=\"jointColor\" />"
218 fragmentBody +=
" <float name=\"blurFactor\" />"
219 fragmentBody +=
" <float2 name=\"uvCoord\" semantic=\"mayaUvCoordSemantic\" flags=\"varyingInputParam\" />"
220 fragmentBody +=
" <float2 name=\"uvFilterSize\" />"
221 fragmentBody +=
" </properties>"
222 fragmentBody +=
" <values>"
223 fragmentBody +=
" <float3 name=\"brickColor\" value=\"0.75,0.3,0.1\" />"
224 fragmentBody +=
" <float3 name=\"jointColor\" value=\"0.75,0.75,0.75\" />"
225 fragmentBody +=
" </values>"
226 fragmentBody +=
" <outputs>"
227 fragmentBody +=
" <float3 name=\"outColor\" />"
228 fragmentBody +=
" </outputs>"
229 fragmentBody +=
" <implementation>"
230 fragmentBody +=
" <implementation render=\"OGSRenderer\" language=\"Cg\" lang_version=\"2.1\">"
231 fragmentBody +=
" <function_name val=\"brickTextureNodePluginFragment\" />"
232 fragmentBody +=
" <source><![CDATA["
233 fragmentBody +=
"float btnplinearstep(float t, float a, float b) \n"
234 fragmentBody +=
"{ \n"
235 fragmentBody +=
" if (t < a) return 0.0f; \n"
236 fragmentBody +=
" if (t > b) return 1.0f; \n"
237 fragmentBody +=
" return (t - a)/(b - a); \n"
238 fragmentBody +=
"} \n"
239 fragmentBody +=
"float3 brickTextureNodePluginFragment(float3 color1, float3 color2, float blur, float2 uv, float2 fs) \n"
240 fragmentBody +=
"{ \n"
241 fragmentBody +=
" uv -= floor(uv); \n"
242 fragmentBody +=
" float v1 = 0.05f; float v2 = 0.45f; float v3 = 0.55f; float v4 = 0.95f; \n"
243 fragmentBody +=
" float u1 = 0.05f; float u2 = 0.45f; float u3 = 0.55f; float u4 = 0.95f; \n"
244 fragmentBody +=
" float du = blur*fs.x/2.0f; \n"
245 fragmentBody +=
" float dv = blur*fs.y/2.0f; \n"
246 fragmentBody +=
" float t = max( \n"
247 fragmentBody +=
" min(btnplinearstep(uv.y, v1 - dv, v1 + dv) - btnplinearstep(uv.y, v2 - dv, v2 + dv), \n"
248 fragmentBody +=
" max(btnplinearstep(uv.x, u3 - du, u3 + du), 1.0f - btnplinearstep(uv.x, u2 - du, u2 + du))), \n"
249 fragmentBody +=
" min(btnplinearstep(uv.y, v3 - dv, v3 + dv) - btnplinearstep(uv.y, v4 - dv, v4 + dv), \n"
250 fragmentBody +=
" btnplinearstep(uv.x, u1 - du, u1 + du) - btnplinearstep(uv.x, u4 - du, u4 + du))); \n"
251 fragmentBody +=
" return t*color1 + (1.0f - t)*color2; \n"
252 fragmentBody +=
"} \n]]>"
253 fragmentBody +=
" </source>"
254 fragmentBody +=
" </implementation>"
255 fragmentBody +=
" <implementation render=\"OGSRenderer\" language=\"HLSL\" lang_version=\"11.0\">"
256 fragmentBody +=
" <function_name val=\"brickTextureNodePluginFragment\" />"
257 fragmentBody +=
" <source><![CDATA["
258 fragmentBody +=
"float btnplinearstep(float t, float a, float b) \n"
259 fragmentBody +=
"{ \n"
260 fragmentBody +=
" if (t < a) return 0.0f; \n"
261 fragmentBody +=
" if (t > b) return 1.0f; \n"
262 fragmentBody +=
" return (t - a)/(b - a); \n"
263 fragmentBody +=
"} \n"
264 fragmentBody +=
"float3 brickTextureNodePluginFragment(float3 color1, float3 color2, float blur, float2 uv, float2 fs) \n"
265 fragmentBody +=
"{ \n"
266 fragmentBody +=
" uv -= floor(uv); \n"
267 fragmentBody +=
" float v1 = 0.05f; float v2 = 0.45f; float v3 = 0.55f; float v4 = 0.95f; \n"
268 fragmentBody +=
" float u1 = 0.05f; float u2 = 0.45f; float u3 = 0.55f; float u4 = 0.95f; \n"
269 fragmentBody +=
" float du = blur*fs.x/2.0f; \n"
270 fragmentBody +=
" float dv = blur*fs.y/2.0f; \n"
271 fragmentBody +=
" float t = max( \n"
272 fragmentBody +=
" min(btnplinearstep(uv.y, v1 - dv, v1 + dv) - btnplinearstep(uv.y, v2 - dv, v2 + dv), \n"
273 fragmentBody +=
" max(btnplinearstep(uv.x, u3 - du, u3 + du), 1.0f - btnplinearstep(uv.x, u2 - du, u2 + du))), \n"
274 fragmentBody +=
" min(btnplinearstep(uv.y, v3 - dv, v3 + dv) - btnplinearstep(uv.y, v4 - dv, v4 + dv), \n"
275 fragmentBody +=
" btnplinearstep(uv.x, u1 - du, u1 + du) - btnplinearstep(uv.x, u4 - du, u4 + du))); \n"
276 fragmentBody +=
" return t*color1 + (1.0f - t)*color2; \n"
277 fragmentBody +=
"} \n]]>"
278 fragmentBody +=
" </source>"
279 fragmentBody +=
" </implementation>"
280 fragmentBody +=
" <implementation render=\"OGSRenderer\" language=\"GLSL\" lang_version=\"3.0\">"
281 fragmentBody +=
" <function_name val=\"brickTextureNodePluginFragment\" />"
282 fragmentBody +=
" <source><![CDATA["
283 fragmentBody +=
"float btnplinearstep(float t, float a, float b) \n"
284 fragmentBody +=
"{ \n"
285 fragmentBody +=
" if (t < a) return 0.0f; \n"
286 fragmentBody +=
" if (t > b) return 1.0f; \n"
287 fragmentBody +=
" return (t - a)/(b - a); \n"
288 fragmentBody +=
"} \n"
289 fragmentBody +=
"vec3 brickTextureNodePluginFragment(vec3 color1, vec3 color2, float blur, vec2 uv, vec2 fs) \n"
290 fragmentBody +=
"{ \n"
291 fragmentBody +=
" uv -= floor(uv); \n"
292 fragmentBody +=
" float v1 = 0.05f; float v2 = 0.45f; float v3 = 0.55f; float v4 = 0.95f; \n"
293 fragmentBody +=
" float u1 = 0.05f; float u2 = 0.45f; float u3 = 0.55f; float u4 = 0.95f; \n"
294 fragmentBody +=
" float du = blur*fs.x/2.0f; \n"
295 fragmentBody +=
" float dv = blur*fs.y/2.0f; \n"
296 fragmentBody +=
" float t = max( \n"
297 fragmentBody +=
" min(btnplinearstep(uv.y, v1 - dv, v1 + dv) - btnplinearstep(uv.y, v2 - dv, v2 + dv), \n"
298 fragmentBody +=
" max(btnplinearstep(uv.x, u3 - du, u3 + du), 1.0f - btnplinearstep(uv.x, u2 - du, u2 + du))), \n"
299 fragmentBody +=
" min(btnplinearstep(uv.y, v3 - dv, v3 + dv) - btnplinearstep(uv.y, v4 - dv, v4 + dv), \n"
300 fragmentBody +=
" btnplinearstep(uv.x, u1 - du, u1 + du) - btnplinearstep(uv.x, u4 - du, u4 + du))); \n"
301 fragmentBody +=
" return t*color1 + (1.0f - t)*color2; \n"
302 fragmentBody +=
"} \n]]>"
303 fragmentBody +=
" </source>"
304 fragmentBody +=
" </implementation>"
305 fragmentBody +=
" </implementation>"
306 fragmentBody +=
"</fragment>"
308 fragmentMgr.addShadeFragmentFromBuffer(fragmentBody.encode(
'utf-8'),
False)
310 def supportedDrawAPIs(self):
311 return omr.MRenderer.kOpenGL | omr.MRenderer.kOpenGLCoreProfile | omr.MRenderer.kDirectX11
313 def fragmentName(self):
314 return "brickTextureNodePluginFragment"
320 sRegistrantId =
"brickTexturePlugin_py"
322 def initializePlugin(obj):
323 plugin = om.MFnPlugin(obj,
"Autodesk",
"4.5",
"Any")
325 userClassify =
"texture/2d:drawdb/shader/texture/2d/brickTexture_py"
326 plugin.registerNode(
"brickTexture_py", brickTextureNode.id, brickTextureNode.creator, brickTextureNode.initialize, om.MPxNode.kDependNode, userClassify)
328 sys.stderr.write(
"Failed to register node\n")
333 omr.MDrawRegistry.registerShadingNodeOverrideCreator(
"drawdb/shader/texture/2d/brickTexture_py", sRegistrantId, brickTextureNodeOverride.creator)
335 sys.stderr.write(
"Failed to register override\n")
338 def uninitializePlugin(obj):
339 plugin = om.MFnPlugin(obj)
341 plugin.deregisterNode(brickTextureNode.id)
343 sys.stderr.write(
"Failed to deregister node\n")
348 omr.MDrawRegistry.deregisterShadingNodeOverrideCreator(
"drawdb/shader/texture/2d/brickTexture_py", sRegistrantId)
350 sys.stderr.write(
"Failed to deregister override\n")