I started studying shaders in Panda, first of all I decided to implement pixel lighting, I found the code for OpenGL and sort of successfully adapted it.
from panda3d.core import CardMaker, Shader
from direct.showbase.ShowBase import ShowBase
def shader():
return Shader.make(Shader.SL_GLSL,
vertex="""
#version 120
varying vec3 v_FragmentPosition;
varying vec3 v_FragmentNormal;
attribute vec2 p3d_MultiTexCoord0;
attribute vec4 p3d_Vertex;
attribute vec3 p3d_Normal;
uniform mat4 p3d_ModelViewProjectionMatrix;
void main( void )
{
gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
v_FragmentPosition = p3d_Vertex.xyz;
v_FragmentNormal = p3d_Normal;
}
""",
fragment="""
#version 120
uniform sampler2D p3d_Texture0;
uniform vec3 pos_light;
uniform vec3 pos_camera;
varying vec3 v_FragmentPosition;
varying vec3 v_FragmentNormal;
const vec4 k_LightColor = vec4(1.0, 0.6, 0.3, 1.0);
const float k_Shininess = 64.0;
const float k_ConstAttenuation = 0.5;
const float k_LinearAttenuation = 0.05;
const float k_QuadricAttenuation = 0.001;
void main( void )
{
vec3 L = pos_light - v_FragmentPosition;
// ** Used in the calculation of light extinction
float distance = length( L );
L = normalize( L );
vec3 N = normalize( v_FragmentNormal );
// ** The H vector is used to calculate the gloss (specularity) of a fragment
vec3 E = normalize( pos_camera - v_FragmentPosition );
vec3 H = normalize( L + E ); // ** Half-vector
// ** The calculation coefficient. attenuations
float attenuation = 1.0 / ( k_ConstAttenuation + k_LinearAttenuation * distance + k_QuadricAttenuation * distance * distance );
float diffuse = clamp( dot( L, N ), 0.0, 1.0 );
float specular = pow( clamp( dot( N, H ), 0.0, 1.0 ), k_Shininess );
if( diffuse <= 0.0 ){
specular = 0.0;
}
vec4 diffuseColor = diffuse * k_LightColor * attenuation;
vec4 specularColor = specular * k_LightColor * attenuation;
vec4 ambientColor = vec4(0.02, 0.02, 0.02, 0.02);
vec4 emissionColor = vec4(0.0, 0.0, 0.0, 0.0);
gl_FragColor = ( diffuseColor + specularColor + ambientColor + emissionColor) * texture2D(p3d_Texture0, gl_TexCoord[0].xy );
}
""")
from direct.showbase.ShowBase import ShowBase
from panda3d.core import NodePath
class TestPointlight(ShowBase):
def __init__(self):
ShowBase.__init__(self)
lihgt = NodePath("lihgt")
lihg_m = loader.load_model("../models/icosphere")
lihg_m.reparent_to(lihgt)
lihgt.setPos(-5, 30, 15)
lihgt.reparent_to(render)
room = loader.load_model("../models/abstractroom")
room.reparent_to(render)
room.set_shader(shader())
room.set_shader_input("pos_light", lihgt.getPos());
room.set_shader_input("pos_camera", camera.getPos());
demo = TestPointlight()
demo.run()
However, I can’t replace gl_MultiTexCoord0 with p3d_MultiTexCoord0, this causes an error:
:display:gsg:glgsg(error): An error occurred while compiling GLSL vertex shader created-shader:
created-shader(16) : error C1035: assignment of incompatible types
The second problem is an artifact with lighting.
I think this is a consequence of the fact that I use input from OpenGL.