Advanced lighting? Shaders?

I would like to ‘beef’ up my program by adding some nice visual effects such as better lighting and shader effects. The problem is I have no idea where to start!

With respect to lighting im simply using 6 point lights, and one ambient light (My program has only one room at present) Ive seen screenshots where the lighting looks awesome, are there any extra options i might not know about?

With shaders, id like to learn how to write shaders, but once again I have no idea where to start… Can I download samples somewhere? Where can I learn cg? Tutorials, books?

any help would be greatly appreciated. Here is what the room looks like now (its a a primitive science lab :smiley: )

you already notices something important… lighting =)
lighting makes up a huge part of what we like to see as “realistic”.
you usually have 4 choices:
using lightmaps
baking lightmaps into textures (works but is a dirty workaround for lightmaps)
using vertex-colors
using realtime
… or mix them all up…

most games use a mixture between lightmaps and vertex-based realtime lights… newer games prefer pixel based realtime+lightmaps
lightmaps for all static stuff and realtime calculations for shadows/light or just lights from dynamic sources.
since this is all confusing because you have alot of possibilitys its better to decide on one thing first. well all depends on your hardware and the tools you use to create your models and and and. to give you a start:

  • realtime lights ->you are using them right now the way they come with panda.mostly vertex-based (in panda by default vertex only).
    unless you use pixel based lighting and own recent hardware your result wont change too much.
    __usual not too nice
    __when looking good->often slow on non-high-end hardware
    __some work required to get it looking good (writing shaders and such)

-lightmaps. a very common way but they first need to be created. i think this is a good choice when using maya and 3dsmax. it somehow should be possible with blender,too but i think there are a problems when it comes to exporters and lightmap creation (definetly possible if you know your way with python and script the stuff).
__lightmaps can give a VERY realistic look when using radiosity or GI-lights (a whole bunch of tools support these, max/maya too)
__no need to subdivide your mesh unnecessary.
__no performance loss
__requires a modelling package wich can export 2 different uv coodrdinate sets

-baked into vertex colors. requires a subdivided mesh (just like lighting in panda) but can be pre-processed using radiosity and such. a nice solution when working with blender. results are pretty good looking and performance is ok
__doable in blender and i guess max and maya
__fairly good results
__still fast
__need to subdivide you levels a little to improve the lighting quality (higher vertex&poly count)
__some smaler issues cause vertex colors darken the mesh.nothing too much.

lightmaps are proven, and good solution… once you figured out how to get them into panda… :stuck_out_tongue:.
there are tools to create them, a some of them can create highly realistic looking stuff and are for free,too. maybe the tool named FSRad might help you. i dont know how and if it can be used with panda at all but i think it works with obj files and its possible to save the lightmaps seperate so it might be possible… perhaps you can find someone who knows about panda and lightmaps. try to search the forum =)

if you cant get it work you might want to use blenders radiosity tools to bake the lighting into the vertexcolor (there are good tutorials on the web abouthow to use blenders radiosity tools). use the egg exporter to save your models (x dont support vertex colors afaik). there is a bug with the alphavalue exported when using radiosity in blender. but you can manually edit the egg file with the “replace” funktion in your texteditor to fix you models

as for shadows from dynamic objects, use soft blob shadows. they wont look too bad most of the time.

well good luck with your work.
thomas e

ps: with per-pixel based realtime lighting you can get doom3/quake4 like games… but with lightmaps(using radiosity) you can get ways more realistic stuff. vertex-backed radiosity is also pretty impressive.

I have been looking through this too, and currently it isn’t too easy to use lightmaps in Blender and export them to Panda3D. If I find something about it, I will post here :slight_smile:

The new blender build makes it very easy.

sorry to wake up a sleeping thread…

I am curious how Panda deals with multiple UVsets and Multiple textures internally.

It seems like a relatively ‘low cost’ approach to making panda3D models look fantastic.

UVSet1 would contain the detail textures (with several textures being applied to different parts of the model. i.e surfaces)

UVSet2 would contain the Lightmap (this UVSet would span the entire Mesh and contain the shadow/light maps

Max/Maya both support multiple UV Sets

internally ? How deep ?
Have you tried –[THIS]–

thanks for the links. I am struggling with this (I’m probably missing something simple, I have just recently started playing with Panda)

problem: I am trying to generate a model that contains 2 texturestages.

“Detail” will contain the detail textures (bricks, floor, wall ) and UV Coordinate set 1 (or texcoord set 1)

“Lightmap” will contain a lightmap and texcoord set 2.

MayatoEgg seems to be able to export this. unfortunately, I don’t use maya. I use 3DS Max 8.
in a maya .egg file, there is a :

<Scalar> uv-name { myUVname }

listed under each texture.

but in the 3DS Max 8 created .egg file their is only one (unnamed) UVset.

to overcome this limitation of the .egg exporter for 3DS Max 8, I thought I could load 2 model files into panda. 1 with the detail textures(and appropriate UV map) and a 2nd with the lightmap texture (and it’s UVmap) and somehow extract the UVset from on and apply it to a 2nd texturestage of the other.

I am so far unsuccessful, here is what I have:

import direct.directbase.DirectStart 
from direct.task import Task 
from import Actor 
from pandac.PandaModules import TextureStage
import math,-20,0)
model = loader.loadModel("../models/light_test_detail") 
top = model.findAllTextureStages()
print top.getNumTextureStages()

lmap_model = loader.loadModel("../models/light_test_lightmap")
lmap_texture = loader.loadTexture("../models/Lightmap.png")
tslist = lmap_model.findAllTextureStages()
ts = tslist[0]
texcoord = ts.getTexcoordName()
newts = TextureStage('newts')
print texcoord
model.setTexture(newts , lmap_texture)
top = model.findAllTextureStages()
print top.getNumTextureStages()

#lmapUVset = lmap_texture.TextureStage.getDefault


My suggestion is not to mess around with a second UV set, just use the default UV set for both textures. To make your detail texture apply at a finer level of detail–that is, larger UV values–apply a scale to the UV’s for that texture stage with setTexScale().


Thanks David, I will have a llok at setScale(). interestingly, when things don’t work, I learn much more than if it worked flawlessly the first time. I am getting my head around textures, texturestages and how these relate to the node in general.

the crux of my question is this.
Can I extract the default UV coordinates from one loaded .egg model and use it on another one as a 2nd texturestage/tex coords?

I am now looking at the EGG file to see if it makes sense to modify that directly via a merge of UV data.

generally, the detail textures are blended witht eh lightmap texture to provide a nice shadow effect.

the only problem with using hte same UV set and adjusting the scale is that the UV coordinate set is different on the two models (they have been unwrapped differently)

I am not trying to hijack this thread, I think a solution to this could be useful to everyone.

Maybe. Not really. To do this, you’d have to be sure that the two egg files loaded exactly the same except for the UV’s. In practice, they probably would, if they started out exactly the same except for the UV’s, but there’s nothing in the system that actually guarantees this, so you might be taking a risk if something changes internally in Panda later (or if you accidentally let your egg files wander just a bit out of sync).

But, if you allow yourself that assumption, you could walk through all the vertices of the one model with a GeomVertexReader, and simultaneously walk through all the vertices of the other one with a GeomVertexWriter–they have exactly the same number and order of vertices, right?–and copy one to the other. (You’d first have to modify the GeomVertexFormat of your target model to add a new column for the new UV’s.)

On the other hand, it might be easier, and much smarter, to do this at the egg level instead. Write a program that would read your two egg files, maybe using simple text reads, or (probably better) using Panda’s egg library; and write out a new egg file that contains the same vertices with the combined UV’s. This program would have an easier time verifying that the vertices matched up one-for-one between the two egg files and could squawk if they got out of sync. And there wouldn’t be the risk of relying on the way Panda munges, or doesn’t munge, the vertices at load time.


Thanks David,
Here is what I have:
you can download it here:

The purpose of this was to export a model with multiple UV sets
from 3DS MAX 8 using the .egg exporter. The .egg exporter is very well written
but does not support multiple UV sets (hopefully it will in the future).
To get around this limitation, I created 2 identical models (lightmap.egg and Detail.egg)
and manually edited the .egg files to create a 3rd .egg file (combined.egg). Like you mentioned, for this to work the vertices need to be identical (which is not a problem for a lightmapped level)

3DS max exporter does not identify a uv-name. since there is only one, it is the default and
looks like this for each vertex:

<UV>  { 1.03995 1.04513 }

you can see this in the “lightmap.egg” or “detail.egg” file that was generated by the 3DS
Max 8 .egg exporter.

the maya exporter handles multple UV Sets and each texture will have something
like this:

<Scalar> uv-name { detailUV }

I added these manually to “combined.egg”

<Scalar> uv-name { lightmapUV }

in addition, each vertex needs to know what the UV coordinates are for each
named set:

<UV> detailUV { -1.13374 -1.15105 }
<UV> lightmapUV { 0.280204 0.280204 }	

In addition, every polygon needs to know about the textures that will be applied
to it (note there are 2 TRef’s per poly, one is the lightmap-Tex66 and
the other is the detail texture (Tex9,19 or 1 in this example):

<Polygon> {
        <RGBA> { 1 1 1 1 }
        <TRef> { Tex19 }
        <TRef> { Tex66 }
        <VertexRef> { 34 35 32 <Ref> { mymesh.verts } }

now i need to come up with a programmatic way to edit these files, as David
mentioned, once the .egg is loaded, the order of the vertices is unpredictable
so these changes need to happen to the file directly.


The 3DS MAx exporter can be modified to support multiple UV sets :slight_smile:

how about using python’s defaul file-reader?
shouldn’t be that hard to use on text-files.

working on it. I am fairly new to python so i get lost pretty quickly. having the .egg files in human readable text is a huge bonus though.

Note that another option is to use Panda’s built-in egg library, which can read, write, and modify egg files from Python code. This is documented in the API documentation starting at EggData and with related classes, and there are a few examples in forum posts here and there.

Probably Python’s text functions are better documented overall, though. :slight_smile:


ut this in the folder from the download i posted above.

this seems to work. it might be too specific for my 3DS Max created models but it was fun to learn some of the Egg stuff. Please provide comments and pointers (I am sure there are better ways of doing this)


from pandac.PandaModules import * 

class myegg:
    def __init__(self):
        self.egg = EggData()
    def ReadEgg(self,eggfile):
        self.firstnode = self.egg.getFirstChild()
        self.MyTextures = []
        self.g = self.egg.getChildren()
        for self.etype in self.g:
            if self.etype.getClassType() == EggComment.getClassType():
                self.MyEggComment = self.etype
               # print "found EggComment type"
            if self.etype.getClassType() == EggTexture.getClassType():
               # print "found EggTexture type"
            if self.etype.getClassType() == EggGroup.getClassType():
       = self.etype
                self.mygroupL1 =
               # print self.mygroupL1
                for n in self.mygroupL1:
                    if n.getClassType() == EggGroup.getClassType():
                        self.mygroupL2 = n.getChildren()
                      #  print self.mygroupL2 
                        for nn in self.mygroupL2:
                            if nn.getClassType() == EggGroup.getClassType():
                                self.mygroupL3 = nn.getChildren()
                             #   print self.mygroupL3                 #print n
                                for vg in self.mygroupL3:
                                    if vg.getClassType() == EggVertexPool.getClassType():
                                        self.myVertPool = vg
                                        self.numverts = self.myVertPool.getHighestIndex()
                #print  #.getNextChild().getName()
               # print "found Eggroup type"   
    def addTexture(tex):
    def addUvNameToTexture(self,texture , uvname ):
    def addUvNameToVertices(self , uvname ):
        for vert in range(self.numverts+1):
            uv = self.myVertPool[vert].getUv()
            self.myVertPool[vert].setUv(uvname , uv)
    def addTrefToPolygons(self, texture):
        for poly in self.mygroupL3:
            if poly.getClassType() == EggPolygon.getClassType():
                print "GGGGG" # add tref of lightmap

lmap = myegg()
for tx in lmap.MyTextures:
    lmap.addUvNameToTexture(tx , 'lightmapUv')

detail = myegg()
for tx in detail.MyTextures:
    detail.addUvNameToTexture(tx , 'detailUv')


def transferUvs( fromegg , toegg , uvname ):
    fromVP = fromegg.myVertPool
    toVP = toegg.myVertPool
    if fromegg.numverts <> toegg.numverts:
        return false
    for i in range(fromegg.numverts+1):
        fuv = fromVP[i].getUv()
        toVP[i].setUv( uvname , fuv )
transferUvs( lmap , detail , 'lightmapUv' )
detail.egg.addChild(lmap.MyTextures[0])         # add the lightmap texture