Scripted multipass render to add outlines?

zigraphixzigraphix Posts: 2,768

I'm trying to composite an image from two render passes to try to combine outlines (and maybe other effects) with the main image render. I've corresponded a bit with one of the developers, and I'm getting closer, but I'm still not quite getting it to work. Here are the hints I have so far:


- Use the existing scripted rendering example to generate one or more outline images (there are different methods that can be combined)
- As one part of this, modify the addOutLineIDsToMaterialsProperties() function in the OutlineGlobals.dsa script to set each node (object in the scene) to have a different Color ID
- Write an imager shader that takes the outline image(s) as uniquely named parameters and composites them with the render (I know how to do this part with Shader Mixer).
- In the script, set the image input properties on the imager camera to the outline file(s) before you execute a newly added "standard pass" at the end

Here are the parts I don't know how to do. If anyone could point me toward documentation -- new, old, examples, RiSpec, whatever-- I'd really appreciate it!

1 - To set the newly created OutlineColorID property in the materials of each node, I have in mind to add a line inside the k loop that looks something like this:

oMaterial.setFloatValue(g_sOUTLINE_COLOR_ID_PROPERTY_NAME, i);

Here, i is the node number. I'm not sure about oMaterial.setFloatValue or its parameters, though. Should I be using oColorIDProp instead?

2 - Assuming I have a Shader Mixer camera that can layer the images, and it is the active camera, how do I assign the parameters of that camera to the appropriate filenames generated previously from within this script? Or should I not be using Shader Mixer, and instead write that part of the imager in the script?

Thanks in advance for any pointers!

Post edited by zigraphix on
«13

Comments

  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    Um... anyone?

    Could someone at least make a guess as to when the scripting documentation will be updated? The DS 3.x docs that come with the Script Development Kit don't seem to cover this area.

  • ketthroveketthrove Posts: 62
    edited December 1969

    zigraphix said:
    I'm trying to composite an image from two render passes to try to combine outlines (and maybe other effects) with the main image render. I've corresponded a bit with one of the developers, and I'm getting closer, but I'm still not quite getting it to work. Here are the hints I have so far:


    - Use the existing scripted rendering example to generate one or more outline images (there are different methods that can be combined)
    - As one part of this, modify the addOutLineIDsToMaterialsProperties() function in the OutlineGlobals.dsa script to set each node (object in the scene) to have a different Color ID
    - Write an imager shader that takes the outline image(s) as uniquely named parameters and composites them with the render (I know how to do this part with Shader Mixer).
    - In the script, set the image input properties on the imager camera to the outline file(s) before you execute a newly added "standard pass" at the end

    Here are the parts I don't know how to do. If anyone could point me toward documentation -- new, old, examples, RiSpec, whatever-- I'd really appreciate it!

    1 - To set the newly created OutlineColorID property in the materials of each node, I have in mind to add a line inside the k loop that looks something like this:

    oMaterial.setFloatValue(g_sOUTLINE_COLOR_ID_PROPERTY_NAME, i);

    Here, i is the node number. I'm not sure about oMaterial.setFloatValue or its parameters, though. Should I be using oColorIDProp instead?

    2 - Assuming I have a Shader Mixer camera that can layer the images, and it is the active camera, how do I assign the parameters of that camera to the appropriate filenames generated previously from within this script? Or should I not be using Shader Mixer, and instead write that part of the imager in the script?

    Thanks in advance for any pointers!

    1. For this you want to:
    a. Get the Materials from the node
    b. Find the property (findProperty should work for this)
    c. Set the value of the property (setColorValue() is probably what you want unless
    you changed the property to a float property in which case SetValue is what you want)

    2. For this:
    a. Name the images properties you want to set for your camera something original using the
    properties tab in shader mixer
    b. Get the active camera
    c. Call find property with your original name from step a
    d. Set the image on the property
    e. Render final pass

  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    Thank you!

    I will make this an open, documented script if I can get it working. I'm at work right now, but I hope to be able to work on this tonight.

  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    ketthrove said:

    1. For this you want to:
    a. Get the Materials from the node
    b. Find the property (findProperty should work for this)
    c. Set the value of the property (setColorValue() is probably what you want unless
    you changed the property to a float property in which case SetValue is what you want)

    Ok. In the OutlineGlobals sample script, which I'm working from, there's a loop in the function function addOutLineIDsToMaterialsProperties() that starts

        for( var k = 0; k < oShape.getNumMaterials(); k += 1 ){     var oMaterial = oShape.getMaterial(k);     if( oMaterial ){      var oColorIDProp = oMaterial.findProperty( g_sOUTLINE_COLOR_ID_PROPERTY_NAME );  ...

    How do I format the color value here, where I've entered XXXX?

    
           oColorIDProp.setColorValue(g_sOUTLINE_COLOR_ID_PROPERTY_NAME, XXXX);
    

    I want to manipulate this value with i, so it will change per object in the scene. But I've tried a couple of different values and generally the scene turns out all black or the render crashes.

  • Richard HaseltineRichard Haseltine Posts: 19,838
    edited December 1969

    setColorValue takes first a colour, or a time and then a colour, as far as i can see - it looks as if you are passing a string, then trying to add a colour value. I think you want to just put a randomised or procedurally generated colour value in there, with not other values.

  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    Should the color value be in hexidecimal format, e.g. #FFFFFF? Quotes, no quotes? Or do I need to construct a value from an RGB triplet?

  • Richard HaseltineRichard Haseltine Posts: 19,838
    edited December 1969

    As I recall you need to construct from a triplet. - new DzColor( r , g, b) I think, though I know it took a bit of fiddling to get it right.

  • zigraphixzigraphix Posts: 2,768
    edited September 2012

    The DAZ Script 2 reference (.../Program Files/DAZ 3D/DAZStudio3/docs/DAZScript/class_color.html) has the constructor as just "Color", so would I do something like this?

    
    
    var TheColor = Color(r, g, b); // where r, g, and b are defined integers 0-255
    oColorIDProp.setColorValue(TheColor);
    
    

    Sorry if these are dumb questions, I'm just having a lot of trouble wrapping my head around this scripting language, especially with changes that still don't seem to be documented yet....

    Post edited by zigraphix on
  • Richard HaseltineRichard Haseltine Posts: 19,838
    edited December 1969

    That looks right, yes. As I said, it took me a couple of attempts to make it work and it was answering a forum question rather than a script of my own so I don't have it to refer to.

  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    Ok, I'll play around with it tonight (I'm at work right now) and post my findings. Thanks for the help!

  • zigraphixzigraphix Posts: 2,768
    edited September 2012

    Ok, I've pretty much got the unique ColorID part working. The modification to the function addOutLineIDsToMaterialsProperties looks like this:

    ...       oColorIDProp.setPath( "Outline" );       var iColor = i*19+16;       var jColor = j*19+16;       var kColor = k*19+16;       if (iColor > 255) {iColor -= 255;}       if (jColor > 255) {jColor -= 255;}       if (kColor > 255) {kColor -= 255;}       var TheColor = Color(iColor, jColor, kColor); // where r, g, and b are defined integers 0-255       oColorIDProp.setColorValue(TheColor);...

    I've attached sample images of the default 3Delight render, the render produced by the Scripted Renderer, which creates an image of flat colors using the ColorIDs, the outline file using ColorIDs, and the outline file using Normals. I still don't know if using the ColorIDs would be all that helpful, but it might add some enhancement over just Normals. Anyway, I'm happy to have figured out how to get this working, whether or not I end up using it.

    One thing that still confuses me is that the cube, a DS primitive, doesn't seem to get a ColorID other than (0,0,0), even though I've deliberately set the starting point of all ColorID components above 0. Is a DS primitive not a regular node/shape in the scene tree?

    Outline_Frm0_Normal.png
    490 x 584 - 63K
    Outline_Frm0_ColorID.png
    490 x 584 - 48K
    spugglesColorID.png
    490 x 584 - 44K
    spuggles3Delight.png
    490 x 584 - 286K
    Post edited by zigraphix on
  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    Progress. I had to switch out the display setup to render the outline images as jpg rather than tif in OutlineRenderScript.dsa, because I couldn't figure out how to multiply tif images with the regular render to get the outlines, but this is what I have now... first I have to switch to scripted 3Delight and pick the outline script I want to use, render, then switch back to regular 3Delight and render again with my custom camera to pick up the pre-named image and combine it with the regular render.

    So next up, I need to figure out how to get a normal render, rather than the color ID render, in the OutlineRenderScript.dsa script. And then I need a script that pulls in the custom camera and alters the Render Engine to Scripted 3Delight and selects my script. Getting closer! Thanks to everyone who has helped. :)

    outline_test_render.png
    490 x 584 - 202K
  • ReDaveReDave Posts: 815
    edited December 1969

    WOW!!! That outline-only picture looks *great*! Congratulations!!!

  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    Wit 'till you see it combined with my sketch camera. ;-)

  • TugpsxTugpsx Posts: 142
    edited December 1969

    zigraphix said:
    Progress. I had to switch out the display setup to render the outline images as jpg rather than tif in OutlineRenderScript.dsa, because I couldn't figure out how to multiply tif images with the regular render to get the outlines, but this is what I have now... first I have to switch to scripted 3Delight and pick the outline script I want to use, render, then switch back to regular 3Delight and render again with my custom camera to pick up the pre-named image and combine it with the regular render.

    So next up, I need to figure out how to get a normal render, rather than the color ID render, in the OutlineRenderScript.dsa script. And then I need a script that pulls in the custom camera and alters the Render Engine to Scripted 3Delight and selects my script. Getting closer! Thanks to everyone who has helped. :)

    I use a loader script to swap out the 3Delight for my own. This opens the door for tons more addons and render engines.

    NewD2ODemo.jpg
    651 x 849 - 157K
  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    Yes, that's the kind of script I had in mind. Is there a reference example you can point me to?

    (Octane, eh? I should look into that sometime....)

  • TugpsxTugpsx Posts: 142
    edited December 1969

    Works great for DS4.5 too

    Newoctane4.5_.jpg
    473 x 627 - 82K
  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    Cool, I hope to test it tonight. :)

  • zigraphixzigraphix Posts: 2,768
    edited November 2012

    Back again.

    The part I'm trying to work on now is the render script. What I need to do is combine the features of two existing scripted renderer examples: "Outline" and "Standard Example." I need to create an ordinary render as in Standard Example, but I also need to insert a pass to render the outlines and save to a file in a known location.

    I thought this was probably something I could manage, but I'm having trouble. I pulled up both sets of scripts in jEdit and used diff to locate the points of departure. I decided to use the Standard Example as the base for my new script and essentially copied all the parts of Outline that were different into Standard Example, then created a new pair of directories (in Scripts and in Resources) and saved. (Actually I moved the originals out of the way so I wouldn't have to fuss with paths).

    Edited-- initially I had a crash on render problem, but in looking through the logs, I found the variable I hadn't defined correctly. Now my outline files are created correctly, and my normal render occurs... but it doesn't seem to produce the correct final render. I'm looking through the logs again... I suspect I'll have another question. But no point in leaving all this code in the thread.

    Post edited by zigraphix on
  • zigraphixzigraphix Posts: 2,768
    edited November 2012

    Argh. Never mind.

    Post edited by zigraphix on
  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    ketthrove said:
    zigraphix said:

    2 - Assuming I have a Shader Mixer camera that can layer the images, and it is the active camera, how do I assign the parameters of that camera to the appropriate filenames generated previously from within this script? Or should I not be using Shader Mixer, and instead write that part of the imager in the script?

    Thanks in advance for any pointers!


    2. For this:
    a. Name the images properties you want to set for your camera something original using the
    properties tab in shader mixer
    b. Get the active camera
    c. Call find property with your original name from step a
    d. Set the image on the property
    e. Render final pass

    Ok, I think this is where I'm stuck now. My script generates outlines, I save them to a known location, my camera can take in the outline file and composite it over the render... but when I'm using the Scripted Render, it doesn't seem to use the active camera, so the composition doesn't occur (and neither do any of the other camera effects).

    If I can get this to work, we can have cameras that do this without modifying the materials of any object in the scene:

    tooncam.jpg
    490 x 584 - 75K
  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    It seems to me that the bit of code I need to modify is in this section:

    // Set up the cameraRenderer.cameraProject( Camera, sizeRender.width, sizeRender.height );// Set up crop windowRenderer.setCropWindow( oHandler );// Set up the display(s)Renderer.doDefaultDisplay();// Set the background color; from the active viewportif( BackDrop && BackDrop.getTexture()  ){ Renderer.renderBackDrop( BackDrop, sizeRender.width, sizeRender.height );} else { // TODO: Check for DzShaderCamera & DzBrickCamera with Imager var oViewportMgr = MainWindow.getViewportMgr(); var oViewport = oViewportMgr.getActiveViewport(); var o3DViewport = oViewport.get3DViewport();  aTokens = [ "color bgcolor" ]; //aParams = [ [o3DViewport.background.red, o3DViewport.background.green, o3DViewport.background.blue] ]; aParams = [ o3DViewport.background ]; Renderer.riImager( "background", aTokens, aParams );}

    In particular, I suspect the " // TODO: Check for DzShaderCamera & DzBrickCamera with Imager" notation is referencing what I need. However, I've been through the DAZ Script 2 documentation for DzShaderCamera and DzBrickCamera and I don't see a way to get the active camera there. I suspect the global variable "Camera" has this information, because the line to set up the camera uses this variable, as do many other parts of the code, and they all work correctly. Shadow maps are correctly generated, for example. I think somehow the first line in this code snippet needs to be changed to reflect that I'm using a Brick Camera. I'm just not finding the documentation of how to do that....

  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    I finally came across a reference to getActiveCamera in the DS3 documentation for DzBasicCamera:

    file:///C:/Program Files/DAZ 3D/DAZStudio3/docs/DAZScript/class_dz_basic_camera.html#272ecc3f25e54ecb4efb2e3ef6e26b6c

    I added this to the beauty pass:

    //get the active camera
     var oViewportMgr = MainWindow.getViewportMgr();
     var oViewport = oViewportMgr.getActiveViewport();
     var o3DViewport = oViewport.get3DViewport();
     var oActiveCamera = o3DViewport.getActiveCamera();
    
    // Set up the camera
    Renderer.cameraProject( oActiveCamera, sizeRender.width, sizeRender.height );
    

    and now when I render, I get the "outlineid" version of the render, rather than rendering through the camera as defined in the scene. This looks the same as it would in the scripted renderer example for outlines.

    Of course, this isn't the render I want. At a guess, the "active camera" changes during the outline render pass, and I need to switch it back to the original camera after that completes....

    toon_outline_color_ids.jpg
    490 x 490 - 32K
  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    I have now confirmed that the "Standard Example" does not support Brick Cameras. Without an updated set of docs for the scripting dev kit that includes the brick functions, I think I'm stuck. :( Here's hoping someone out there has a version of a scripted renderer that supports a Shader Mixer "Brick Camera."

  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    I found a reference to some DS 4.5 scripting here:

    http://docs.daz3d.com/doku.php/public/software/dazstudio/4/referenceguide/scripting/start

    Unfortunately, it's not complete yet. The Object Index hasn't been written. A sample script explains how to render to the viewport here:

    http://docs.daz3d.com/doku.php/public/software/dazstudio/4/referenceguide/scripting/api_reference/samples/rendering/render_to_viewport/start

    but this seems to have been written specifically for the regular 3Delight renderer, not the scripted renderer, and I can't see how to integrate any of what I see here with the script bits I already have. In particular, there is a call that seems to be about getting the active camera, but I'm not convinced it gets a brick camera-- I tried inserting it in a couple of places in my code and I still just get a render from the viewpoint of the current camera, but ignoring the brick-based camera shader I've defined. :(

    Supposing that there is some analogy between DzBrickCamera and DzShaderCamera, do I maybe want to use something like this?

    file:///C:/Program Files/DAZ 3D/DAZStudio3/docs/DAZScript/class_dz_shader_camera.html#cc29733a690be9cee94bf379bf0e54e4

    e.g.

    oCamera.setDisplay(name, type, mode, aTokens, aParams)

    Or maybe it should be Camera, not oCamera:

    These methods affect the camera at render-time, and are provided for the render-time script only. Calling these functions from outside the render-time script will have no effect. A global transient variable named Camera - refering to the current DzShaderCamera - exists for the duration of the render-time script. Referencing this variable from outside a render-time script will result in an error.

    I'm sorry to keep asking these clueless questions, but without docs, I'm kind of stuck. The brick shaders being a particular feature of Daz Studio, I don't think any other references are likely to help, are they?

  • ketthroveketthrove Posts: 62
    edited December 1969

    The oCamera is the current camera the user is looking through in the viewport. If you want to check if the camera is a spesific subclass you can use inherits("classname"). If you want to use a particular brick camera or shader camera you need to ensure it in the scene and then find it with the methods on Scene, or instruct the user to insert it and make it active before rendering.

  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    ketthrove said:
    The oCamera is the current camera the user is looking through in the viewport. If you want to check if the camera is a spesific subclass you can use inherits("classname"). If you want to use a particular brick camera or shader camera you need to ensure it in the scene and then find it with the methods on Scene, or instruct the user to insert it and make it active before rendering.

    Ok, all that is good to know, but when I am looking through a brick camera in the viewport, and then I use the Standard Example with the scripted renderer, the render uses some kind of default camera from that angle, not the brick camera that should be the active camera. Is this a bug? Or is there something I need to do to let the script know that the active camera is a brick camera?

  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    Steps to reproduce:

    Start DS4.5

    add some content to the scene, e.g. a sphere

    open Shader mixer tab

    File->New Shader, select Camera

    Add Imager root, Toon brick, Backdrop brick (see attached screenshot)

    Create camera

    Select camera

    Render - note toon shading (see tooncamtest1)

    Open Render Settings tab

    Select Render Engine: Scripted 3Delight

    Select Render Script: Standard Example

    Render - note that there is no toon shading (see tooncamtest2)

    If you switch back to the non-scripted 3Delight renderer, the toon functionality of the Shader Mixer camera returns.

    So, is this a bug in the scripted renderer function, or does the script need to explicitly support a Shader Mixer camera?

    tooncamtest2.jpg
    490 x 490 - 18K
    tooncamtest1.jpg
    490 x 490 - 15K
    SimpleToonCam.png
    674 x 262 - 21K
  • ketthroveketthrove Posts: 62
    edited December 1969

    zigraphix said:
    ketthrove said:
    The oCamera is the current camera the user is looking through in the viewport. If you want to check if the camera is a spesific subclass you can use inherits("classname"). If you want to use a particular brick camera or shader camera you need to ensure it in the scene and then find it with the methods on Scene, or instruct the user to insert it and make it active before rendering.

    Ok, all that is good to know, but when I am looking through a brick camera in the viewport, and then I use the Standard Example with the scripted renderer, the render uses some kind of default camera from that angle, not the brick camera that should be the active camera. Is this a bug? Or is there something I need to do to let the script know that the active camera is a brick camera?

    Sorry I forgot to mention something, you need to edit this section:

    // Set the background color; from the active viewportif( BackDrop && BackDrop.getTexture()  ){ Renderer.renderBackDrop( BackDrop, sizeRender.width, sizeRender.height );} else { // TODO: Check for DzShaderCamera & DzBrickCamera with Imager var oViewportMgr = MainWindow.getViewportMgr(); var oViewport = oViewportMgr.getActiveViewport(); var o3DViewport = oViewport.get3DViewport();  aTokens = [ "color bgcolor" ]; //aParams = [ [o3DViewport.background.red, o3DViewport.background.green, o3DViewport.background.blue] ]; aParams = [ o3DViewport.background ]; Renderer.riImager( "background", aTokens, aParams );}

    You need to remove it or move it before "Renderer.cameraProject.." if you are tying to keep the imager as specfied in the Brick/Shader camera

    Oh and I missed remembered "Camera" not "oCamera" is the current camera.

  • zigraphixzigraphix Posts: 2,768
    edited December 1969

    ketthrove said:

    You need to remove it or move it before "Renderer.cameraProject.." if you are tying to keep the imager as specfied in the Brick/Shader camera

    Oh and I missed remembered "Camera" not "oCamera" is the current camera.

    Ok, I'll try that tonight. Thanks!

Sign In or Register to comment.
Rocket Fuel