Skip to content

Read me

wezu edited this page Jan 26, 2017 · 1 revision

Intro

This project was created as a drop-in replacement for the Panda3D ShaderGenerator (also known as the Auto Shader). The shader generator allows to use the Panda3D engine without the need to write any shaders. At the time when that system was created the Nvidia Cg shading language was considered (one of) the best solutions for writing shaders as it worked both on Direct3D and OpenGl, unfortunately now (in 2017) Cg is as good as dead and the list of features that the ShaderGenerator supports is, and probably will stay limited.

There are other efforts to make Panda3D more accessible to people who don't want to write their own shaders, most notably the RenderPipeline by tobspr (https://github.com/tobspr/RenderPipeline)... in fact the RenderPipeline is the only one I'm aware of at this time.

Unlike the RenderPipeline, that focuses of Physical Based Rendering on OpenGL 4.x hardware, this project is aimed to run basically on a potato and present acceptable 'last gen' graphics.

I would also like to note, that although the initial aim was to make this system a drop-in replacement, with little to none effort needed on the user part, the default Panda3D light interface has been sacrificed in the name of simplicity, and users wanting to switch from the ShaderGenerator will need to re-write their lights.

Basic

Installation

To install the system you will need to clone or download the source from https://github.com/wezu/p3d_auto_deferred_shader . You will need the 'data', 'shaders' and 'volume' directories (with their content) and also the 'deferred_render.py' script. To use the system you will need to import the DeferredRenderer and the light classes from deferred_render.py and initialize the DeferredRenderer.

from deferred_render import *
DeferredRenderer()

You don't need to keep a reference to the DeferredRenderer instance a it installs itself into the buildins, a terrible crime as far as Python purist are concerned, but it shouldn't be shocking to Panda3D users, as that's exactly the same thing that ShowBase does. You may also pass some configuration parameters when creating the DeferredRenderer instance, but you don't need to, the system has reasonable defaults and all the settings can be changed at a later time.

Usage

Models

Once the DeferredRenderer instance is created, you will get a new node called 'defered_render'. You can reparent nodes (models) to this node to make them visible, just as you would normally reparent things to 'render'. You will also have another node called 'forward_render', nodes reparented to that will be rendered using a forward rendering shader - you may need to write your own shaders for forward rendering (or request them, I'm might be willing to write them). The forward rendering should only be used for transparent objects as transparency will not work with any form of deferred rendering (without shenanigans).

Lights

The system offers 3 types of lights:

  • SphereLight
  • ConeLight
  • SceneLight

SphereLight is a point (omni) light. It shines in all directions with the given color, illuminates everything in a given radius and the intensity of the light drops with distance (more or less with a inverse square ratio, reaching zero at the lights radius). When creating a SpherLight you need to provide all these values my_light=SphereLight(color=(0.4,0.4,0.6), pos=(2,3,2), radius=8.0) After creating a SphereLight you can change its properties at will (there are also functions to do this, but properties are so much nicer)

my_light.color=(1.0, 0.0, 0.5)
my_light.pos=(2, 3, 8.5)
my_light.radius=25.8

To remove a SphereLight from your scene, simply delete it.

del my_light

Note that if the reference to the light goes out of scope it will get garbage collected and removed from the scene, you may want to put your lights in a dict, list or set (or something like self.my_light=... )

ConeLight is a spotlight. It shines in just one direction with the given color, illuminates everything in a given radius and the intensity of the light drops with distance (more or less with a inverse square ratio, reaching zero at the lights radius). ConeLight behaves just like SpereLight, it just has some extra parameters

my_light = ConeLight(color=(0.8, 0.8, 0.4), pos=(0,0,5), look_at=(10, 0, 0), radius=15.0, fov=30.0) 

'fov' is the Field Of View of the light (given in degrees), the fov should be greater then 0.0 and less then 180.0, the recommended values are somewhere between 10 and 120 degrees. 'look_at' is the position (or node!) that the light will look at. If you're not familiar with the Panda3D NodePath.look_at() function, you should go and correct that error. You can also use a hpr paramater to point the light in the direction you want - the light looks down the Y axis just like the Panda3D Spotlight (or Camera).

SceneLight is a directional light, but it would be more precise to say SceneLight are directional lights, because you can have multiple directional lights as part of one SceneLight. This weirdness comes from the fact that in deferred shading directional lighting is calculated in a full screen quad, just as you would do any image post-processing and to make things a bit simpler all directional lights get applied in one go. If you just want one directional light in your scene then you don't need to think about the additional light and use it just like other lights

my_light=SceneLight(color=(0.3, 0.3, 0.1), direction=(-0.5, 0.5, 1.0))  

If you want to add mode directional lights use the add_light() function:

my_light.add_light(color=(0.0, 0.0, 0.2), direction=(0.5, -0.5, -1.0), name='backlight')

You can change the parameters of the light using set_color() and set_direction() functions, and remove lights with remove_light()

my_light.set_color(color=(1.0, 1.0, 0.0))#set the main light color
my_light.set_color(color=(1.0, 1.0, 0.0), name='main')#set the main light color
my_light.set_color(color=(0.0, 0.0, 5.0), name='backlight')#set the 'backlight' light color
my_light.remove_light(name='backlight') 
#remove all the lights
del my_light

##Configuration

Presets

The most simple way to configure the renderer is to use presets. The system comes with some pre-defined options and you can use them by simply telling the renderer to use one of the presets:

DeferredRenderer(preset='full') 

These presets are:

####'full'

  • Geometry is rendered using Parallax Occlusion Mapping
  • Ambient Occlusion
  • Bloom
  • Fog
  • Depth of Field
  • Screen Space Reflection
  • Color mapping with a lookup table (LUT)
  • Dithering
  • FXAA anti aliasing

####'medium'

  • Geometry is rendered using Parallax Occlusion Mapping
  • Ambient Occlusion (at half resolution)
  • Bloom
  • Fog
  • Color mapping with a lookup table (LUT)
  • Dithering
  • FXAA anti aliasing

####'minimal'

  • FXAA anti aliasing

Advanced

To be written...

Custom Configuration

Changing Configuration at Runtime

Filter Inputs and Defines

Default Textures

Writing Your Own Shaders