Material won't render until...

On 16/04/2018 at 17:59, xxxxxxxx wrote:

I'm stumped by an issue with a created hair material not rendering at first.
I create a spline, a hair material, a hair tag, and then add the tag to the spline.
Just to be safe I do this:

mat.Update(True, True)   

If I drop the material into the console I see:
<c4d.BaseMaterial object called 'Fade: 1/Hair Material' with ID 1017730 at 0x00000181D66C5350>

If I drop the tag into the console I see:
<c4d.BaseTag object called 'Tag: Fade: 1/Hair Material' with ID 1017729 at 0x00000181D66C5410>

The ID's look correct.

The problem is it won't render by either pressing "Render View" or pressing "Render to Picture Viewer."

I then tried clicking on Material box>Menu>Function>Render All Materials.
This doesn't cause them to render.

What does work, is clicking:
Material box>Menu>Create>Shader>Hair Material.
And then rendering.

I don't apply the newly created shader; in fact, I can delete it before I render, and the previously non-rendering materials render perfectly.

Just the act of creating a hair shader suddenly makes C4D render correctly.
What the heck?

Further testing:

  1. If I save the non-rendering scene to a file, and then close C4D, re-open C4D and load the file, it still doesn't render.

  2. If I create the hair shader with the menu, delete it, and then save the scene to a file.  Upon reloading the scene, everything renders correctly.  Once the scene has had a menu created shader, it will render fine, even if saved and reloaded.

What is C4D doing?

I've uploaded the file so you can see for yourself:

I'm using R17 by the way.



On 17/04/2018 at 05:33, xxxxxxxx wrote:

Hi Chris,

when creating the Hair material manually, you also need to create a "Hair Render" VideoPost and add it to the render settings (RenderData.InsertVideoPost()). When creating a Hair Material from the user interface, this is done implicitly and thus "fixes" your scene.
Roughly like so:

vpHair = c4d.documents.BaseVideoPost(c4d.VPhair)
rd = doc.GetActiveRenderData()

On 17/04/2018 at 10:18, xxxxxxxx wrote:


This doesn't work in R17.
It looks like the docs say 'BaseVideoPost' is new in R19:

The console printed out:

AttributeError: 'module' object has no attribute 'BaseVideoPost'

How do I do this prior to R19?



On 17/04/2018 at 10:42, xxxxxxxx wrote:

I went back to the R14 docs and it says:


Inserts pvp as the last video post in this render setting.

_<_t_<__<_t_<__<_t_<__<_t_>__ield-"="">Parameters: pvp  ( BaseList2D ) – The vid_<_t_>_ost to insert.

So I tried this:

vpHair = c4d.BaseList2D(c4d.VPhair)
rd = doc.GetActiveRenderData()

This caused it to render perfectly with a new doc.

Will this method work on R14+, including R19?

EDIT - This is explored in my next post.
Also, since a user can do this over and over, does it matter if 'InsertVideoPostLast' occurs over and over.  Should I be checking if the render data already has a 'C4D.VPhair' inserted?



On 17/04/2018 at 14:34, xxxxxxxx wrote:

Well, I checked the 'Render Settings' box, and sure enough every time the code executes it adds another "Hair Render" to the list.  So I did this:

rd = doc.GetActiveRenderData()
fp = rd.GetFirstVideoPost()
# If fp isn't 'None'
#print fp    # Prints:  '<c4d.BaseList2D object called 'Hair Render/Hair Render' with ID 1017325 at 0x000001C9E857EB50>''
#print fp.GetTypeName()     # Prints: 'Hair Render'
# How do you get the ID above to test for VPhair?
#c4d.VPhair = 1017325
if fp == None or fp.GetTypeName() != 'Hair Render':   # GetName() also works.
    #vpHair = c4d.documents.BaseVideoPost(c4d.VPhair)   # R19+
    vpHair = c4d.BaseList2D(c4d.VPhair)

This works.  Now, they don't stack up in the 'Render Settings' box.

However, because I'm only checking the first post with:

fp = rd.GetFirstVideoPost()

It doesn't work if something else is inserted first like this:

vpLens = c4d.BaseList2D(1001049)

So, what needs to be done is to iterate over everything in the 'Render Settings' box to look only for 'Hair Render'.

How do I do that?

Also, I'd rather test for

ID == c4d.VPhair

instead of using

GetTypeName() != 'Hair Render'

But I can't find a way to extract the ID from this:

<c4d.BaseList2D object called 'Hair Render/Hair Render' with ID 1017325 at 0x000001C9E857EB50>

How do you do that?


On 18/04/2018 at 09:49, xxxxxxxx wrote:

Hi Chris,

sorry, I missed the R17 hint...
Your solution is fine. and you are right, you should check, if the VideoPost is already there.
Just get the first VideoPost (GetFirstVideoPost()) and then iterate through with GetNext() and check for the ID with CheckType(). While I link to our current R19 docs, this works the same in R17.
Like so:

rd = doc.GetActiveRenderData()
vp = rd.GetFirstVideoPost()
found = False
while vp is not None:
    if vp.CheckType(c4d.VPhair) : # alternatively compare the return value of GetType()
        found = True
    vp = vp.GetNext()

On 18/04/2018 at 13:08, xxxxxxxx wrote:


Thanks for you help.
Everything is working properly now.