Announcement

Collapse
No announcement yet.

per-frame shader operations

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • per-frame shader operations

    Hi all,

    I've created my own version of the TexAColor plugin that does some ray casting based on a locator point in the Maya scene. So basically, I want to set a plugin attribute to the position of the locator every frame.

    I'm familiar with the 'Post Translate Python' functionality to send scene information to the Vray plugin during translation from Maya to Vray and I'm doing this as follows:

    Code:
    import vray.utils as vu
    import maya.cmds as mc
    
    mat = vu.exportMaterial('lambert1')
    tex = vu.exportTexture('myTexAColor')
    mat.get('brdf').set('color_tex', tex)
    
    locPos = mc.xform('locator1', q=True, t=True)
    tex.set('locatorPos', vu.Vector(locPos))
    
    nodes = vu.findByType('Node')
    
    nodes[1].set('material', mat)
    However, I'd like to update the 'locatorPos' attribute in the plugin every frame. There is the 'Pre Render Frame MEL' functionality but when I try to recall this code in that block or just update locPos and recall 'tex.set('locatorPos', vu.Vector(locPos))', Maya crashes with a generic 'cannot save blah.ma to temp directory' message. So something is wrong.

    Perhaps I need to actually create a corresponding Maya plugin for this Vray plugin but I haven't investigated that path yet. Alternatively, what would be the best way to update Vray plugin attributes based on Maya scene elements per frame?

    Thanks,

  • #2
    Ah, so I found this thread discussing per-frame operations. Still digesting it but hoping I don't have to do something too terribly custom to make this work!

    Comment


    • #3
      This is not going to work through the Python callback. Instead, in recent versions (2.x nightly builds and 3.x beta/nightly), V-Ray can automatically create a Maya shading node for your plugin (see the docs/maya_sdk.html file for more info). You can then connect the inputs of that Maya shading node to other attributes in the scene, like the locator position, and V-Ray should be able to pick up and export the animation correctly. If you are using an older V-Ray build, you will have to write the Maya shading node yourself.

      Best regards,
      Vlado
      I only act like I know everything, Rogers.

      Comment


      • #4
        Thanks Vlado, I was able to add X, Y, Z number attribute definitions to my shader desc file and connect these to a locator translate X, Y, Z in Maya hypershade... I tried passing as a vector or transform directly but Maya wasn't recognizing these attributes right away so I just defaulted to individual X, Y, Z values.

        Comment


        • #5
          Ok; good that you found a way. I will check what may be wrong with vector/transform attributes.

          Best regards,
          Vlado
          I only act like I know everything, Rogers.

          Comment


          • #6
            Hey vlado,

            I'm getting sporadic errors when rendering frames in Maya with my modified TexAColor plugin... mind looking over it in case I'm doing anything really wrong? Sometimes is works, sometimes not. I just want to make sure I'm handling resources correctly and not introducing a memory leak or something. Basically, I've customized getTexColor to shade based on a ray cast from a different locator point in the scene:

            Code:
            // Parameters
            struct myTexAColor_Params: VRayParameterListDesc {
            	myTexAColor_Params(void) {
            		// Add the parameters
            		addParamPlugin("uvwgen", EXT_UVWGEN);
            		addParamTexture("texture");
            		addParamFloat("vecLocX", 0);
            		addParamFloat("vecLocY", 0);
            		addParamFloat("vecLocZ", 0);
            	}
            };
            
            struct myTexAColor: VRayTexture, RTTexInterface {
            	myTexAColor(VRayPluginDesc *pluginDesc):VRayTexture(pluginDesc) {
            		// Set parameter caches
            		paramList->setParamCache("uvwgen", &uvwgen_plugin);
            		paramList->setParamCache("texture", &texture);
            		paramList->setParamCache("vecLocX", &vecLocX);
            		paramList->setParamCache("vecLocY", &vecLocY);
            		paramList->setParamCache("vecLocZ", &vecLocZ);
            	}
            
            	void renderBegin(VR::VRayRenderer *vray);
            	void renderEnd(VR::VRayRenderer *vray);
            	void frameBegin(VR::VRayRenderer *vray);
            	void frameEnd(VR::VRayRenderer *vray);
            
            	AColor getTexColor(const VRayContext &rc);
            	void getTexColorBounds(AColor &cmin, AColor &cmax);
            	Vector getColorBumpGradient(const VRayContext &rc);
            private:
            	// Cached parameters
            	PluginBase* uvwgen_plugin;
            	UVWGenInterface* uvwgen;
            	TextureInterface *texture;
            	Vector vecLoc;
            	Vector sceneOffset;
            	float vecLocX;
            	float vecLocY;
            	float vecLocZ;
            	Color outColor;
            
            	// The color cache
            	ShadeCache<AColor, true, false> shadeCache;
            public:
            	// From RTTexInterface
            	PluginBase* getPlugin(void) { return this; }
            	int getDataSize(void) { return 0; }
            	void getData(float *fdata) { }
            
            	PluginInterface *newInterface( InterfaceID id ) {
            		if (EXT_RTTEX==id) return static_cast<PluginInterface*>( (RTTexInterface*)this );
            		return VRayTexture::newInterface(id);
            	}
            	
            	virtual int getSource(const char *part,const char *outParam,const char *lang,VUtils::ShaderSource &shaderSrc, OCLData &mtlData)
            	{
            		if (0==strcmp(lang, "ParamList")) {
            			shaderSrc.append("texture\n");
            			return 1;
            		}
            
            		if (NULL==texture) {
            			shaderSrc.printf("%s = (float4)(0.5f, 0.5f, 0.5f, 1.0f);\n", outParam);
            			return 0;
            		}
            
            		if (stricmp(part, "color")!=0) return 0;
            
            		PluginBase *texmapPlugin=texture->getPlugin();
            		if (NULL==texmapPlugin) return 0;
            
            		RTTexInterface *rttex=static_cast<RTTexInterface*>(GET_INTERFACE(texmapPlugin, EXT_RTTEX));
            		if (NULL==rttex) return 0;
            
            		if (0==strcmp(lang, "MaterialDescriptor")) {
            			rttex->getSource("color", "", lang, shaderSrc, mtlData);
            			return 1;
            		}
            
            		char tempColorStr[64];
            		sprintf(tempColorStr, "tempColor%d", getRTTexID());
            
            		shaderSrc.printf("float4 %s;\n", tempColorStr);
            		shaderSrc.append("{\n");
            		rttex->getSource("color", tempColorStr, lang, shaderSrc, mtlData);
            		shaderSrc.append("}\n");
            
            		shaderSrc.printf("%s=%s;\n", outParam, tempColorStr);
            
            		return 1;
            	}
            };
            
            #define myTexAColor_PluginID PluginID(LARGE_CONST(20051228001))
            SIMPLE_PLUGIN_LIBRARY(myTexAColor_PluginID, EXT_TEXTURE, "myTexAColor", "myTexAColor shader for VRay", myTexAColor, myTexAColor_Params);
            
            void myTexAColor::renderBegin(VR::VRayRenderer *vray) {
            	VRayTexture::renderBegin(vray);
            	shadeCache.renderBegin(vray);
            
            	sceneOffset = Vector(0, 0, 0);
            	vecLoc = Vector(0, 0, 0);
            }
            
            void myTexAColor::renderEnd(VR::VRayRenderer *vray) {
            	VRayTexture::renderEnd(vray);
            	shadeCache.renderEnd(vray);
            }
            
            void myTexAColor::frameBegin(VR::VRayRenderer *vray) {
            	// other stuff
            	sceneOffset = vray->getFrameData().sceneOffset;
            
            	// Call the base class to update the parameter caches
            	VRayTexture::frameBegin(vray);
            
            	// Call frameBegin on the shade cache
            	shadeCache.frameBegin(vray);
            
            	// Get the uvw gen
            	uvwgen=(UVWGenInterface*) GET_INTERFACE(uvwgen_plugin, EXT_UVWGEN);
            }
            
            void myTexAColor::frameEnd(VR::VRayRenderer *vray) {
            	VRayTexture::frameEnd(vray);
            	shadeCache.frameEnd(vray);
            }
            
            AColor myTexAColor::getTexColor(const VRayContext &rc) {
            	VR::VRayContext &nrc = rc.newSpawnContext(0, Color(1.0, 1.0, 1.0), RT_TRANSPARENCY, -rc.rayresult.normal);
            
            	vecLoc.set(vecLocX, vecLocY, vecLocZ);
            	VR::Vector vecLoc_cam = vecLoc - sceneOffset;
            	VR::Vector dir = normalize0(rc.rayresult.wpoint - vecLoc_cam);
            	VR::TracePoint p = vecLoc_cam;
            
            	nrc.rayparams.mint = 0.0;
             	nrc.rayparams.maxt = LARGE_FLOAT;
            	nrc.rayparams.rayOrigin = nrc1.rayparams.tracedRay.p = p;
            	nrc.rayparams.viewDir = nrc1.rayparams.tracedRay.dir = dir;
            
            	VR::IntersectionData isData;
            	int res = nrc1.vray->findIntersection(nrc, &isData1);
             
            	if (res) {
            		nrc.setRayResult(res, &isData);
            
            		if (nrc.rayresult.sb) {
            			nrc.mtlresult.clear();
            			nrc.rayresult.sb->shade(nrc);
            
            			outColor = nrc.mtlresult.color;
            		} else {
            			outColor = Color(1.0, 0.0, 0.0);
            		}
            	} else {
            		outColor = Color(1.0, 1.0, 1.0);
            	}
            
            	nrc.releaseContext();
            
            	return outColor;
            }

            Comment


            • #7
              Ok, I think I've narrowed down the crashing to the shade call:

              Code:
              nrc.rayrsult.sb->shade(nrc);
              When I set outColor to a solid color in this block and not actually shade, it works consistently. But maybe that was obvious.

              Comment


              • #8
                There is something strange in your code and I couldn't get it to compile right away - sometimes you use nrc1, and sometimes nrc, but nrc1 is not defined anywhere. Same for isData and isData1.

                Is it the intention that nrc1 and nrc on the one hand, and isData1 and isData on the other, are one and the same thing?

                Best regards,
                Vlado
                I only act like I know everything, Rogers.

                Comment


                • #9
                  Sorry, I think all the 1s are typos, so those could be ignored. nrc1 should just be nrc and isData1 should just be isData.

                  Thanks for looking into this. I've gotten to the point where I can prevent crashing. I think what was happening was my secondary ray cast was sometimes hitting my textured surface again and trying to call shade on itself which probably led to a crash.

                  But my biggest question at this point is how do I define my secondary ray to make sure it doesn't hit my surface (the original rc hit surface... the one in which this texture plugin is applied to) again. I know there is the rayparams.skipTag member, and I'm trying to do something like the following:
                  Code:
                  nrc.rayparams.skipTag = rc.rayresult.primitive
                  in order that the new ray I generate does not register a hit on the original surface, but when I check if (nrc.rayresult.primitive == rc.rayresult.primitive) or if (isData.sb == rc.rayresult.sb) it will still occasionally evaluate to true although (per my understanding) this should never be the case as the hit primitive from the original rc should be skipped due to the skipTag being set to it... am I doing/thinking about this correctly?

                  Comment


                  • #10
                    The primitive in the skip tag normally represents just the triangle that was hit, not the entire object.

                    The way to do what you want is to continue tracing the ray through all intersections, comparing the "sb" pointer in the resulting intersection data until it is different from the original. For example something like
                    Code:
                    for (int i=0; i<5; i++) { // Put some limit, just in case; it could be more than 5
                    	VR::IntersectionData isData;
                    	isData.clear();
                    
                    	int rres=nrc.vray->findIntersection(nrc, &isData);
                    	if (!rres)
                    		break; // We didn't intersect anything
                    	else if (isData.sb==rc.rayresult.sb) {
                    		// We intersected the same object, trace on
                    		nrc.rayparams.skipTag=nrc.rayresult.skipTag;
                    		nrc.rayparams.mint=nrc.rayresult.wpointCoeff;
                    	} else {
                    		// We intersected a different object
                    		nrc.setRayResult(rres, &isData);
                    		// Do stuff
                    		// ....
                    		break;
                    	}
                    }
                    Best regards,
                    Vlado
                    I only act like I know everything, Rogers.

                    Comment


                    • #11
                      Thanks again, I believe I've been able to achieve my desired functionality... just had to wrap my mind around the API

                      Comment


                      • #12
                        Ok then, let me know if there is anything else.

                        Best regards,
                        Vlado
                        I only act like I know everything, Rogers.

                        Comment

                        Working...
                        X