Blender as a GLSL editor

Any news?
If it’s can be helpful: I can’t reproduce a problem if I use all three inputs as vec4. In original example used Vec4 + Vec3 + vec3.
Seems that it something with pointers size. I am not familiar with c++ and pandas source, but this code looks strange for me (glShaderContext_src.cxx):

        switch(_ptr._dim[1]) {
          case 1: gsg->_glUniform4fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue;
          case 2: gsg->_glUniform4fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue;
          case 3: gsg->_glUniform4fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue;
          case 4: gsg->_glUniform4fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue;
        }

Of course I can talk nonsense )

You’re right, that should be glUniform1fv, 2fv, 3fv and 4fv instead of all glUniform4fv.

That’s not where it happens, though, the non-array vector inputs are passed further down in that function. I think I found the problem, though - a while ago, CMU students extended the shader system to allow for vec3 inputs, but they only made it work with arrays. I’ll check in a fix momentarily.

I’ve checked in something that appears to have fixed it for me. The fix will be included in 1.8.1 - could you try the latest devel build to see if it works for you?

Seems it works ) The only thing - this time I tested it on windows because I am not found last compiled version for Linux. If it matters, I can try to build Panda from source, but I do not have this experience.

It should not make a difference. Thanks for testing and for reporting this issue!

Thanks for fix ) Ok, back to the topic, I have two question:

  1. Shader are associated with the Blender’s material, but in Panda it’s applyed to the NodePath. As far as I can see, after loading model in Panda we have NodePath, splitted into as many geoms as many materials we have. Can we get those geoms by material names or somehow else to make link between material and shader?

  2. As I know, we can’t save additional information in the egg, except tags. I mean lights, cameras, shaders. Any suggestion on the best way to do it?

  1. I’m not sure what you mean. A “Material” in many other contexts is really a “RenderState” in Panda - ie, all of the setColor, setLight, setShader, and setMaterial calls that define how a model looks. The Material class itself simply stores some parameters that are used in the default shader, so to speak.

Keep in mind that a RenderState can be applied at the individual Geom level as well, it does not need to be applied at the GeomNode level.

  1. You can set a specific property in the Logic panel in Blender, and they will be exported as a tag in the .egg file. Lights will be exported as empty nodes from Blender, so you can set some tags on them to specify the type of light and properties like colour. Then, iterate over the model in Panda3D, doing something like this:
for node in root.findAllMatches("**/=LightType=SpotLight"):
  color = eval(node.getTag("LightColor"))
  light = SpotLight("")
  light.setColor(color)
  node.attachNewNode(light)

Since you’re applying these properties to the light object in Blender, which is really exported as an empty node with tags, your lights will have the right position and orientation automatically.

In the future, we may have a native COLLADA loader that supports lights, cameras and shaders.

I mean that single model in the Blender can have several materials which assigned to the different polygons groups and it can have separate shader for each material. So the question is how to determine which shader to which geom belongs in Panda?

For example Material_1 and Material_2 has different shaders

<CoordinateSystem> { Z-up } 
<Material> Material_1 {
  <Scalar> diffr { 0.054096 }
  <Scalar> diffg { 0.000000 }
  <Scalar> diffb { 0.640000 }
  <Scalar> specr { 0.500000 }
  <Scalar> specg { 0.500000 }
  <Scalar> specb { 0.500000 }
  <Scalar> shininess { 12.5 }
  <Scalar> emitr { 0.000000 }
  <Scalar> emitg { 0.000000 }
  <Scalar> emitb { 0.000000 }
}

<Material> Material_2 {
  <Scalar> diffr { 0.640000 }
  <Scalar> diffg { 0.000000 }
  <Scalar> diffb { 0.014321 }
  <Scalar> specr { 0.500000 }
  <Scalar> specg { 0.500000 }
  <Scalar> specb { 0.500000 }
  <Scalar> shininess { 12.5 }
  <Scalar> emitr { 0.000000 }
  <Scalar> emitg { 0.000000 }
  <Scalar> emitb { 0.000000 }
}

  <Group> Plane {
    <Transform> {
      <Matrix4> {
        1.000000 0.000000 0.000000 0.000000 
        0.000000 1.000000 0.000000 0.000000 
        0.000000 0.000000 1.000000 0.000000 
        0.000000 0.000000 0.000000 1.000000 
      }
    }
    
    <VertexPool> Plane {
    
      <Vertex> 0 {
        -1.0 -0.009277536533772945 0.0
        
        <UV>  {
          0.017424 0.978085
        }
      }
      <Vertex> 1 {
        1.0 -0.009277536533772945 0.0
        
        <UV>  {
          0.982548 0.975124
        }
      }
      <Vertex> 2 {
        1.0 2.0 0.0
        
        <UV>  {
          0.985523 1.944725
        }
      }
      <Vertex> 3 {
        -1.0 2.0 0.0
        
        <UV>  {
          0.020399 1.947686
        }
      }
      <Vertex> 4 {
        -1.0 -2.0 0.0
        
        <UV>  {
          0.014477 0.017438
        }
      }
      <Vertex> 5 {
        1.0 -2.0 0.0
        
        <UV>  {
          0.979601 0.014477
        }
      }
      <Vertex> 6 {
        1.0 -0.009277536533772945 0.0
        
        <UV>  {
          0.982548 0.975124
        }
      }
      <Vertex> 7 {
        -1.0 -0.009277536533772945 0.0
        
        <UV>  {
          0.017424 0.978085
        }
      }}
    
    
    <Polygon> {
      <MRef> { Material_2 }
      <Normal> {0.000000 0.000000 1.000000}
      <VertexRef> { 0 1 2 3 <Ref> { Plane }}
    }
    <Polygon> {
      <MRef> { Material_1 }
      <Normal> {0.000000 0.000000 1.000000}
      <VertexRef> { 4 5 6 7 <Ref> { Plane }}
    }
  }

I’m sorry, I still don’t quite understand. By “shader”, you’re referring to a Panda shader, correct? Since materials are applied per polygon, and there is no way to apply tags to polygons, you will have to group all polygons with a certain shader together and then use a tag on that group to indicate that it should receive the shader.

Both - Blender and Panda - we’re talking about how to use Blender’s shaders in Panda or how to use Blender as GLSL editor.

Perhaps my English is too bad to explain my problem : ( , so I’ll try to draw :slight_smile:

We can set on the whole NodePath, not on the separate geoms, but we must sure that we’re apply exported GLSL to the appropriate geoms.
Problem is that we can’t determine which shader to which geom must applied because we can’t associate material name or or something else with the Panda’s geom.

As far as I know, since Geoms cannot store tags, if you load an .egg file with tags on different groups, these groups will be exported as separate PandaNodes, and not as a single GeomNode with multiple Geoms. So, you don’t even need to worry about the Geom level; just look for tags on the nodes and then apply the shaders to the nodes.

It shouldn’t be too hard to add support for shaders in .egg files; it would be pretty cool if Blender’s .egg export would automatically embed the GLSL shader.

Not quite. As far as i can see, if contains some polygons with the different materials, then when it loaded, Panda makes several geoms to applying different or, as you says, “RenderState” on it.
For example if you look at sample above - it contains one group and two polygons with different materials. When I load this model in pview and press Shift+L then pview reports me:

ModelRoot untitled.egg
  GeomNode Plane (2 geoms: S:(MaterialAttrib))

If I apply the same material on the both polygons then the model contains only one geom.

And yes, I have a target on the integration of GLSL exporting into YABEE :slight_smile:

Are you thinking of having a .py file exported too or something?
Or can you set shader inputs in an egg file?

I think, that I need to make custom loader, of course if I solve some problems with exporting and loading shaders, and if the EGG format will not be extended.

I’m thinking that it’s probably worth it to extend the .egg format until we get a native COLLADA loader, I’ve been thinking about doing this for a long time now. I’m excited about the idea of exporting shaders from Blender to Panda.

I’m thinking that there could be entries at the top of an .egg file, similar to how there are and entries. Each entry could specify either paths to the appropriate shader files, or embed the actual shader code, ie:

<Shader> shader1 {
  <Scalar> language { glsl }
  <Scalar> fragment-file { filename1.sha }
  <Scalar> vertex-file { filename2.sha }
}

Or, in the case of a Blender exporter it may be best to avoid using a separate file, and embed the contents directly:

<Shader> shader1 {
  <Scalar> language { glsl }
  <Scalar> fragment-code {
    .. shader code goes here ..
  }
  <Scalar> vertex-code {
    .. shader code goes here ..
  }
}

Or for Cg shaders, which are often (but not necessarily) combined in a single file:

<Shader> shader1 {
  combined-filename.sha
  <Scalar> language { cg }
}

Then, we have an on the polygons to apply the shader just as there are and entries.

Simple shader inputs could be specified on the level if necessary, as follows:

<Group> mygroup {
  <Param> myFloat { 1.03 }
  <Param> myVec { 1 1 0 }
  <Param> myNodeRef { <Ref> { someGroup } }
  ...
}

What do you guys think? If drwr is also onboard with this, then I can probably make this happen before the next release.

Would be pretty sweet.
But even if shader support is added to the egg format it feels like we’ll still need to set most shader inputs manually. Like for lights we’ll need to set the light’s position as shader input ourselves in a task.

Maybe we can have helper functions to make things a little more automatic and clean.

nodePath.setNPPosAsShaderInput('input', lightNP)

I may be missing something obvious though, haven’t used shaders for a while.

This is already supported, you can use setShaderInput(‘input’, lightNP) and declare it as a mat4 in your shader. The position will be in the fourth row.

It’s also why I added the syntax with in there, referring to a different group’s transformation:

<Param> input { <Ref> { myLightNode } }

I’ve been thinking about how to implement more advanced binding, for instance binding to a particular attribute of a light, or binding to the light’s position with respect to a particular coordinate space. But that’ll have to wait until the shader system is redesigned.

Sounds great!

It may be required reference to the “sampler2d” and may be - to the default Panda’s camera, but I am not sure that it’s really neded (we have textures and ref) and not sure how to implement this.

Also I think that we should have a variable in the config.prc or a flag in the loadModel() to disable shader loading. It may be necessary, for example, to loading models on the old hardware.

Should entries be at the top of an egg, or at the top of the entries? Or it’s no matter?

You mean you need to be able to reference the shadow map? I don’t know how that could be currently implemented at the .egg level.

Most if not all graphics hardware supports shaders nowadays. It should not be necessary to add an explicit configuration variable anyway, because Panda will simply not show the shader if the hardware doesn’t support it.

entries would go at the top of the egg file, just like entries. What indicates where they are applied would go in entries in the polygon.

Yes, also I look at the possible uniform types in the Blender API reference blender.org/documentation/bl … iform-type