Hello all,
I am fairly new to shader programming an currently learning with the nvidia cg tutorial.
In chapter 5 the vertex shader receives a struct as input from the application, and now i am curious if i can pass a struct from panda3d to the shader. I guess i can do this with “setShaderInput” but at the moment i always get the following error message: “:gobj(error): shaders/BasicShader.sha: Invalid type for a k-parameter (uniform in unknown k_material.k_shininess)”.
The structs i want to pass to the shader are “Material” and “PointLight” of the following shader:
//Cg
struct Material {
uniform float3 k_Ke;
uniform float3 k_Ka;
uniform float3 k_Kd;
uniform float3 k_Ks;
uniform float k_shininess;
};
struct PointLight {
float4 position;
float3 color;
float kC;
float kL;
float kQ;
};
float attenuation(float3 P,
PointLight light)
{
float d = distance(P, light.position);
return 1 / (light.kC + light.kL * d +
light.kQ * d * d);
}
void computeLighting(PointLight light,
float3 P,
float3 N,
float3 eyePosition,
float shininess,
out float3 diffuseResult,
out float3 specularResult)
{
float atten = attenuation(P, light);
// Compute the diffuse term
float3 L = normalize(light.position.xyz - P);
float diffuseLight = max(dot(N, L), 0);
diffuseResult = atten * light.color * diffuseLight;
// Compute the specular term
float3 V = normalize(eyePosition - P);
float3 H = normalize(L + V);
float specularLight = pow(max(dot(N, H), 0),
shininess);
if (diffuseLight <= 0) specularLight = 0;
specularResult = atten * light.color * specularLight;
}
void vshader( float3 vtx_position : POSITION,
float3 vtx_normal : NORMAL,
out float4 oPosition : POSITION,
out float3 objectPos : TEXCOORD0,
out float3 oNormal : TEXCOORD1,
uniform float4x4 modelViewProj)
{
float4 position = (position.xyz, 1);
oPosition = mul(modelViewProj, position);
objectPos = position.xyz;
oNormal = vtx_normal;
}
void fshader( float3 vtx_position : TEXCOORD0,
float3 l_normal : TEXCOORD1,
out float4 o_color : COLOR,
uniform PointLight lights[],
Material k_material,
uniform float3 k_globalAmbient,
uniform float3 k_eyePosition)
{
float3 P = vtx_position;
float3 N = normalize(l_normal);
// Compute the emissive term
float3 emissive = k_material.k_Ke;
// Compute the ambient term
float3 ambient = k_material.k_Ka * k_globalAmbient;
// Compute diffuse and specular light
float3 diffuseLight, specularLight;
float3 diffuseSum = 0;
float3 specularSum = 0;
for (int i = 0; i < lights.length; i++)
{
computeLighting(lights[i], vtx_position, l_normal, k_eyePosition, k_material.k_shininess, diffuseLight, specularLight);
diffuseSum += diffuseLight;
specularSum += specularLight;
}
// Modify diffuse and specular light by material constants Kd and Ks
float3 diffuse = k_material.k_Kd * diffuseLight;
float3 specular = k_material.k_Ks * specularLight;
// Mix all
o_color.xyz = emissive + ambient + diffuse + specular;
o_color.w = 1;
}
This is the corresponding python code:
from pandac.PandaModules import Vec3
myShader = Shader.load("shaders/BasicShader.sha")
x = Vec3()
render.setShaderInput("k_material.k_Ke", 0,0,0)
render.setShaderInput("k_material.k_Ka", 0,0,0)
render.setShaderInput("k_material.k_Kd", 0,0,0)
render.setShaderInput("k_material.k_Ks", 0,0,0)
render.setShaderInput("k_material.k_shininess", 0.0)
render.setShaderInput("k_globalAmbient", 0,0,0)
render.setShaderInput("k_eyePosition", 0,0,0)
render.setShader(myShader)
All your comments, hints and suggestions are welcome.