New Cg shader inputs


We have just committed into the CVS a new feature for the panda3D shader system that extends the set of available inputs that can be passed to the Cg shader.

In details:

[size=150]1. Panda3D data types:[/size]
This is complete list of numeric parameters that can now be passed to a Cg shader.

from pandac.PandaModules import Vec4
from pandac.PandaModules import Vec3
from pandac.PandaModules import Vec2

from pandac.PandaModules import Point4
from pandac.PandaModules import Point3
from pandac.PandaModules import Point2

from pandac.PandaModules import Mat4
from pandac.PandaModules import Mat3

# PTA means Pointer to Array
from pandac.PandaModules import PTAMat4
from pandac.PandaModules import PTAMat3

# Point and Vector derive from VecBase
from pandac.PandaModules import PTAVecBase4
from pandac.PandaModules import PTAVecBase3
from pandac.PandaModules import PTAVecBase2

# Pointer to 1D arrays
from pandac.PandaModules import PTAFloat
from pandac.PandaModules import PTADouble

[size=150]2. Passing the inputs:[/size]
All the parameters are passed through the well known function:


[size=150]3. Relationship with Cg data types:[/size]
A complete list of possible Cg data types can be found here:

Our work makes available all the numeric types and arrays of them. By numeric I mean all the parameters belonging to the following classes:

  • CG_PARAMETERCLASS_MATRIXPanda3d types and Cg types are connected only by their size. The size in this case represent the number of elements (scalars) contained by the data type. For example:
x1 = Mat4()
x2 = PTAVecBase4.empty_array(4)
x3 = PTAFloat.empty_array(16)

sizeof(x1) = sizeof(x2) = sizeof(x3) = 16

In practice this means that setShaderInput(pname, element_of_size_16) can be used to set any of the Cg parameters having the same size. For example it is legal to do:

setShaderInput(pname, x1)

uniform float4x4 pname;
uniform float2x4 pname[2];
uniform float4x2 pname[2];
uniform float4   pname[4];
uniform float2   pname[8];
uniform float    pname[16];

//Note: float can be changed to: double, bool, fixed, half

This gives a lot more freedom to the user. Now the user not only has access to the data types represented directly in panda3d (i.e. Mat4 -> float4x4), but also has access to the more exotic types made available by Cg (i.e. bool4x2 :unamused:)

[size=150]4. Putting it all together:[/size]


import os
import sys

#panda imports
import direct.directbase.DirectStart
from pandac.PandaModules import *

def main(argv):
  base.setBackgroundColor(0.1, 0.1, 0.1)
  base.camLens.setNearFar(1.0, 50.0)

  base.accept("escape", sys.exit) 

  camera.setPos(0.0, -15.0, 10.0)
  camera.lookAt(0.0, 0.0, 0.0)
  root = render.attachNewNode("Root")
  teapot = loader.loadModel(os.path.join( os.getcwd(),"teapot.egg"))
  # Shader Inputs
  x1 = Mat4()
  x2 = PTAVecBase4.emptyArray(4)
  x3 = PTAFloat.emptyArray(16)


if __name__ == '__main__':

struct VertexDataIN{
  float4 vtx_position  :POSITION;
  float4 vtx_normal    :NORMAL;
  float4 vtx_color     :COLOR;
  float2 vtx_texcoord0 :TEXCOORD0;

struct VertexDataOUT{
  float4 l_position  :POSITION;
  float4 l_normal    :TEXCOORD1;
  float4 l_color     :COLOR;
  float2 l_texcoord0 :TEXCOORD0;

void vshader(VertexDataIN  IN,
	          out VertexDataOUT OUT,
             uniform float4x4 mat_modelproj)
  OUT.l_position  = mul(mat_modelproj, IN.vtx_position);
  OUT.l_color     = IN.vtx_color;
  OUT.l_normal    = IN.vtx_normal;
  OUT.l_texcoord0 = IN.vtx_texcoord0;

struct ShaderInputs{
  uniform float4x4 pname11;
  uniform float2x4 pname12[2];
  uniform float4x2 pname21[2];
  uniform float4   pname22[4];
  uniform float2   pname31[8];
  uniform float    pname32[16];

void fshader(VertexDataOUT vIN,
	          ShaderInputs   IN,
             out float4 o_color : COLOR)
  o_color = IN.pname11[0][1];
  o_color = IN.pname12[1][0];
  o_color = transpose(IN.pname21[1])[1];
  o_color = IN.pname22[1];
  o_color = float4(IN.pname31[1],0,1);
  o_color = float4(IN.pname32[1],0,1,0);

[size=150]4. Conclusion:[/size]
This feature will be soon documented in the Panda3D manual, in the meanwhile, if you have any doubts or suggestions on how to make the documentation clearer then this post, please let me know.

[size=150]4. Notes:[/size]1. We got rid of the k_ prefix. This update is backward compatible, but the k_ prefix shouldn’t be used any more.

In the old system all inputs Be it Vec3 or Vec4 got converted to a Mat4 first then reconvert to float3 or float4. That does not happen any more right? And if we send Vec3 we can assume it only sends float3 - or 12bytes to the graphics card?

Exactly, the new system, send always the right amount of data. Remember that setShaderInput(name,float) internally becomes setShaderInput(name,Vec4). I couldn’t change that function because I wanted to keep the code backward compatible.

So if you want to sent to the GPU a scalar you should do something like:

setShaderInput(name,PTAFloat) or:
setShaderInput(name,[1]) # that is going to be implicitly casted into a PTAFloat.

Using directly PTA’s, means passing only a pointer, and therefore better performances.

If I try the code at the end of the first post it gives a flat blue teapot. Is that the desired result?

teapot = loader.loadModel(os.path.join( os.getcwd(),"teapot.egg"))

will try to load the teapot from my home directory, i.e. /Users/username/teapot.egg

What works is:

teapot = loader.loadModel("models/teapot.egg")

Yes the final result is supposed to be a blue teapot. Not really exciting, but it is a good way to experiments the new inputs.

Thanks for pointing this out. I had the models in my working directory, and I forgot to change it.

sorry to hijack this tread a little, but I have a question somewhat related.

When/Will Panda3d cg shader will support vector arrays as argument ?

I’m doing a shader to show a polygon inside the triangles.

currently I’m doing:

         uniform float4 k_bordersize,

           uniform float4 k_contour0,
           uniform float4 k_contour1,
           uniform float4 k_contour2,
           uniform float4 k_contour100,
  get_min_value(k_contour0 , k_contour1 , l_pos, laststart, currentcontour, min_value);
    get_min_value(k_contour1 , k_contour2 , l_pos, laststart, currentcontour, min_value);
    get_min_value(k_contour99, k_contour100, l_pos, laststart, currentcontour, min_value);

Unless I’m mistaken. I could do this in cg:

uniform float4 k_contour[101],
for( i =0; i< 99; i++)
{    get_min_value(k_contour[i] , k_contour[i+1] , l_pos, laststart, currentcontour, min_value);

but panda3d doesn’t allow array of vector as shaderInput.

If you download Panda3D from the CVS you’ll have available arrays of vectors (PTAVecBase4) as shader inputs.

And then yes, you could do something like this:

You can find more informations here: … der_Inputs (still under construction)

Are there plans to fix the shader inputs for GLSL after these contributions? It kind of sucks that many GLSL shader inputs are broken in the CVS head now.

I don’t think so. When I asked I was explicitly told not to do it. Instead I think there are plans to add inputs support for DirectX.

Does this break stuff that was working before?

No, it doesn’t. The same set of inputs available before for GLSL is working.

Well, yay for CMU’s secret agenda to push open standards off the table. :unamused:

Actually, I am pretty sure this is Disney Imagineering’s secret agenda…

somewhere there is a chart with the features they want ETC to develop.

Oh, okay. Fair enough.

Honestly, this kind of pisses me off. Such great features were added, and then it appears that it a big part of the implementation was intentionally left out, even such an important part given that Panda3D is an open-source engine and therefore should fully support and emphasis open standards.

Well, I don’t know the whole story here; but I doubt there was any intention to leave useful features out. Panda development has always been very pragmatic: I need features X and Y, so I’ll do them. Feature Z would be nice too, but I only have time to do X and Y right now.

This is, of course, both a good thing and a bad thing. It’s good, because it’s part of what makes Panda so useful in practice–it has actually been used to do real projects and has the features needed to make it happen. It’s bad, because it means that the set of features supported may be only a subset of the available features in an interface, which can be frustrating to new users.

As to the open standards thing, I agree that it would be nice to support open standards to the extent possible. But I also see the pragmatism in keeping the DirectX layer from getting too far behind. (In addition to improving support on a wider variety of Windows PC’s, having good support for two different backends helps keeps the high level interface clean.)

David … c_renderer

Why is this bad?


I think this is exactly what happened.

Sorry I didn’t mean to be mysterious. I will ask someone who still has a copy to post it.

I recently asked Federico some questions. The answers maybe useful to the general public:

1) Do these array inputs only work with advanced profiles?

As long as the profile supports them, yes they do. I think, exception made for texture arrays, they should be all supported by arbfp1 etc…

2) Is there a limit to how large an array input can be? ~256?

Yes there is. It depends on the size of the registers of the graphics card. Should be around 16k. For example 256 matrices 4x4 of floats.

  1. Is it possible to index an array in the vertex shader?
    Of course. You can do something like:

#define SIZE 256
int array[SIZE];

I downloaded the

“advanced shader inputs Demo (Perlin Noise applied to a sphere)”

Tested it on my Mac. It’s there but it’s just full screen grey flickering. Maybe good for certain recreational purposes … but … doesn’t this work on Mac?

Also notice that

teapot = loader.loadModel(os.path.join( os.getcwd(),"plane.egg"))

doesnt work. Looks at the home directory instead of the script directory.

Yeah it should work. The sphere is actually behind you when you run the app, so either move the mouse backward or forward and it will appear.

By the way the demo is not even for recreational purpose, we didn’t polish the code and keys do not work as expected etc… I did it only because we needed a stupid demo fast to show for our project.

Take a look at the flocking Ralph demo instead.