Added light ramps and gloss maps

This commit is contained in:
Josh Yelon 2008-02-04 22:49:48 +00:00
parent 6bcd255ec7
commit 005bc25282
8 changed files with 160 additions and 108 deletions

View File

@ -61,6 +61,7 @@
lensNode.I lensNode.h \
light.I light.h \
lightAttrib.I lightAttrib.h \
lightRampAttrib.I lightRampAttrib.h \
lightLensNode.I lightLensNode.h \
lightNode.I lightNode.h \
loader.I loader.h \
@ -172,6 +173,7 @@
lensNode.cxx \
light.cxx \
lightAttrib.cxx \
lightRampAttrib.cxx \
lightLensNode.cxx \
lightNode.cxx \
loader.cxx \
@ -278,6 +280,7 @@
lensNode.I lensNode.h \
light.I light.h \
lightAttrib.I lightAttrib.h \
lightRampAttrib.I lightRampAttrib.h \
lightLensNode.I lightLensNode.h \
lightNode.I lightNode.h \
loader.I loader.h \

View File

@ -26,6 +26,7 @@ INLINE void AttribSlots::
clear_to_zero() {
_alpha_test = NULL;
_antialias = NULL;
_audio_volume = NULL;
_clip_plane = NULL;
_color = NULL;
_color_blend = NULL;

View File

@ -47,6 +47,7 @@ initialize_defvals() {
_defvals._depth_write = DCAST(DepthWriteAttrib,DepthWriteAttrib::make(DepthWriteAttrib::M_on));
_defvals._fog = DCAST(FogAttrib,FogAttrib::make_off());
_defvals._light = DCAST(LightAttrib,LightAttrib::make_all_off());
_defvals._light_ramp = DCAST(LightRampAttrib,LightRampAttrib::make_identity());
_defvals._material = DCAST(MaterialAttrib,MaterialAttrib::make_off());
_defvals._render_mode = DCAST(RenderModeAttrib,RenderModeAttrib::make(RenderModeAttrib::M_unchanged));
_defvals._rescale_normal = DCAST(RescaleNormalAttrib,RescaleNormalAttrib::make_default());
@ -75,6 +76,7 @@ initialize_defvals() {
_defvals._depth_write = DCAST(DepthWriteAttrib,_defvals._depth_write->make_default());
_defvals._fog = DCAST(FogAttrib,_defvals._fog->make_default());
_defvals._light = DCAST(LightAttrib,_defvals._light->make_default());
_defvals._light_ramp = DCAST(LightRampAttrib,_defvals._light_ramp->make_default());
_defvals._material = DCAST(MaterialAttrib,_defvals._material->make_default());
_defvals._render_mode = DCAST(RenderModeAttrib,_defvals._render_mode->make_default());
_defvals._rescale_normal = DCAST(RescaleNormalAttrib,_defvals._rescale_normal->make_default());
@ -118,6 +120,7 @@ AttribSlots(const AttribSlots &copy) :
_depth_write(copy._depth_write),
_fog(copy._fog),
_light(copy._light),
_light_ramp(copy._light_ramp),
_material(copy._material),
_render_mode(copy._render_mode),
_rescale_normal(copy._rescale_normal),
@ -153,6 +156,7 @@ operator =(const AttribSlots &src) {
_depth_write = src._depth_write;
_fog = src._fog;
_light = src._light;
_light_ramp = src._light_ramp;
_material = src._material;
_render_mode = src._render_mode;
_rescale_normal = src._rescale_normal;
@ -188,55 +192,20 @@ get_slot(int n) const {
case 12: return DCAST(RenderAttrib, _depth_write);
case 13: return DCAST(RenderAttrib, _fog);
case 14: return DCAST(RenderAttrib, _light);
case 15: return DCAST(RenderAttrib, _material);
case 16: return DCAST(RenderAttrib, _render_mode);
case 17: return DCAST(RenderAttrib, _rescale_normal);
case 18: return DCAST(RenderAttrib, _shade_model);
case 19: return DCAST(RenderAttrib, _shader);
case 20: return DCAST(RenderAttrib, _stencil);
case 21: return DCAST(RenderAttrib, _tex_gen);
case 22: return DCAST(RenderAttrib, _tex_matrix);
case 23: return DCAST(RenderAttrib, _texture);
case 24: return DCAST(RenderAttrib, _transparency);
case 15: return DCAST(RenderAttrib, _light_ramp);
case 16: return DCAST(RenderAttrib, _material);
case 17: return DCAST(RenderAttrib, _render_mode);
case 18: return DCAST(RenderAttrib, _rescale_normal);
case 19: return DCAST(RenderAttrib, _shade_model);
case 20: return DCAST(RenderAttrib, _shader);
case 21: return DCAST(RenderAttrib, _stencil);
case 22: return DCAST(RenderAttrib, _tex_gen);
case 23: return DCAST(RenderAttrib, _tex_matrix);
case 24: return DCAST(RenderAttrib, _texture);
case 25: return DCAST(RenderAttrib, _transparency);
default:
nassertr(false, NULL);
return NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: AttribSlots::set_slot
// Access: Public
// Description: set the contents of the nth slot.
////////////////////////////////////////////////////////////////////
void AttribSlots::
set_slot(int n, const RenderAttrib *val) {
switch(n) {
case 0: _alpha_test = DCAST(AlphaTestAttrib, val); break;
case 1: _antialias = DCAST(AntialiasAttrib, val); break;
case 2: _audio_volume = DCAST(AudioVolumeAttrib, val); break;
case 3: _clip_plane = DCAST(ClipPlaneAttrib, val); break;
case 4: _color = DCAST(ColorAttrib, val); break;
case 5: _color_blend = DCAST(ColorBlendAttrib, val); break;
case 6: _color_scale = DCAST(ColorScaleAttrib, val); break;
case 7: _color_write = DCAST(ColorWriteAttrib, val); break;
case 8: _cull_bin = DCAST(CullBinAttrib, val); break;
case 9: _cull_face = DCAST(CullFaceAttrib, val); break;
case 10: _depth_offset = DCAST(DepthOffsetAttrib, val); break;
case 11: _depth_test = DCAST(DepthTestAttrib, val); break;
case 12: _depth_write = DCAST(DepthWriteAttrib, val); break;
case 13: _fog = DCAST(FogAttrib, val); break;
case 14: _light = DCAST(LightAttrib, val); break;
case 15: _material = DCAST(MaterialAttrib, val); break;
case 16: _render_mode = DCAST(RenderModeAttrib, val); break;
case 17: _rescale_normal = DCAST(RescaleNormalAttrib, val); break;
case 18: _shade_model = DCAST(ShadeModelAttrib, val); break;
case 19: _shader = DCAST(ShaderAttrib, val); break;
case 20: _stencil = DCAST(StencilAttrib, val); break;
case 21: _tex_gen = DCAST(TexGenAttrib, val); break;
case 22: _tex_matrix = DCAST(TexMatrixAttrib, val); break;
case 23: _texture = DCAST(TextureAttrib, val); break;
case 24: _transparency = DCAST(TransparencyAttrib, val); break;
default: nassertv(false);
}
}

View File

@ -26,6 +26,7 @@
#include "renderAttrib.h"
#include "alphaTestAttrib.h"
#include "antialiasAttrib.h"
#include "audioVolumeAttrib.h"
#include "clipPlaneAttrib.h"
#include "colorAttrib.h"
#include "colorBlendAttrib.h"
@ -38,6 +39,7 @@
#include "depthWriteAttrib.h"
#include "fogAttrib.h"
#include "lightAttrib.h"
#include "lightRampAttrib.h"
#include "materialAttrib.h"
#include "renderModeAttrib.h"
#include "rescaleNormalAttrib.h"
@ -48,7 +50,6 @@
#include "texGenAttrib.h"
#include "textureAttrib.h"
#include "transparencyAttrib.h"
#include "audioVolumeAttrib.h"
////////////////////////////////////////////////////////////////////
// Class : AttribSlots
@ -74,6 +75,7 @@ class EXPCL_PANDA_PGRAPH AttribSlots
CPT(DepthWriteAttrib) _depth_write;
CPT(FogAttrib) _fog;
CPT(LightAttrib) _light;
CPT(LightRampAttrib) _light_ramp;
CPT(MaterialAttrib) _material;
CPT(RenderModeAttrib) _render_mode;
CPT(RescaleNormalAttrib) _rescale_normal;
@ -95,9 +97,8 @@ class EXPCL_PANDA_PGRAPH AttribSlots
public:
// Each "array" reference requires a switch and a DCAST, so it's not overly fast.
enum { slot_count=24 };
enum { slot_count=26 };
const RenderAttrib *get_slot(int n) const;
void set_slot(int n, const RenderAttrib *attrib);
private:
static AttribSlots _defvals;

View File

@ -53,6 +53,7 @@
#include "lensNode.h"
#include "light.h"
#include "lightAttrib.h"
#include "lightRampAttrib.h"
#include "lightLensNode.h"
#include "lightNode.h"
#include "loader.h"
@ -403,6 +404,7 @@ init_libpgraph() {
LensNode::init_type();
Light::init_type();
LightAttrib::init_type();
LightRampAttrib::init_type();
LightLensNode::init_type();
LightNode::init_type();
Loader::init_type();
@ -482,6 +484,7 @@ init_libpgraph() {
GeomNode::register_with_read_factory();
LensNode::register_with_read_factory();
LightAttrib::register_with_read_factory();
LightRampAttrib::register_with_read_factory();
LODNode::register_with_read_factory();
MaterialAttrib::register_with_read_factory();
ModelNode::register_with_read_factory();

View File

@ -2,6 +2,7 @@
#include "lensNode.cxx"
#include "light.cxx"
#include "lightAttrib.cxx"
#include "lightRampAttrib.cxx"
#include "lightLensNode.cxx"
#include "lightNode.cxx"
#include "loader.cxx"

View File

@ -15,41 +15,6 @@
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
//
// Lighting calculations. These can be done either in tangent space
// or model space. Doing them in tangent space is necessary for
// normal mapping. However, it is only possible if tangents have
// been computed. If not, then model space is the only option.
// The parameters needed for lighting are:
//
// Model Space:
//
// vshader:
// model-space normal - varying
// model-space vertex position - varying
// fshader:
// model-space normal - varying
// model-space vertex position - varying
// model-space light position (spot or point) - uniform
// model-space light vector (directional) - uniform
// model-space eye position - uniform
//
// Tangent Space:
//
// vshader:
// model-space normal - varying
// model-space tangent - varying
// model-space binormal - varying
// model-space light position (spot or point) - uniform
// model-space light vector (directional) - uniform
// model-space eye position - uniform
// fshader:
// model-space vertex position - varying
// tangent-space light vector, one per light - varying
// tangent-space eye vector - varying
// model-space light position (spot) - uniform
//
/////////////////////////////////////////////////////////////////////
#include "renderState.h"
@ -244,7 +209,7 @@ analyze_renderstate(const RenderState *rs) {
}
}
// Determine whether model-space or tangent-space lighting is recommended.
// Determine whether lighting is needed.
if (_attribs._light->get_num_on_lights() > 0) {
_lighting = true;
@ -295,9 +260,36 @@ analyze_renderstate(const RenderState *rs) {
if ((s[0]!=0.0)||(s[1]!=0.0)||(s[2]!=0.0)) {
_have_specular = true;
}
} else if (_map_index_gloss >= 0) {
_have_specular = true;
}
}
// Decide whether to separate ambient and diffuse calculations.
if (_have_ambient && _have_diffuse) {
if (_material->has_ambient()) {
if (_material->has_diffuse()) {
_separate_ambient_diffuse = _material->get_ambient() != _material->get_diffuse();
} else {
_separate_ambient_diffuse = true;
}
} else {
if (_material->has_diffuse()) {
_separate_ambient_diffuse = true;
} else {
_separate_ambient_diffuse = false;
}
}
}
if (_attribs._light_ramp->get_mode() != LightRampAttrib::LRT_identity) {
if (_separate_ambient_diffuse) {
pgraph_cat.error() << "Light Ramp incompatible with separate ambient/diffuse\n";
_separate_ambient_diffuse = false;
}
}
// Does the shader need material properties as input?
_need_material_props =
@ -325,6 +317,7 @@ clear_analysis() {
_have_diffuse = false;
_have_emission = false;
_have_specular = false;
_separate_ambient_diffuse = false;
_map_index_normal = -1;
_map_index_height = -1;
_map_index_glow = -1;
@ -381,18 +374,22 @@ create_shader_attrib(const string &txt) {
// - vertex colors
// - lighting
// - normal maps
// - gloss maps
// - materials, but not updates to materials
// - modulated 2D textures
// - texture stage modes: modulate, decal, add
// - light ramps (for cartoon shading)
//
// Not yet supported:
// - 3D textures
// - cube textures
// - texture stage modes: decal, blend, replace, add, etc.
// - texture stage modes: replace, blend
// - color scale attrib
// - texgen
// - texmatrix
// - gloss maps
// - glow maps
// - glow maps (not yet sure what these should do)
// - other TextureStage::Modes
// - cartoon thresholding and other special effects
//
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) ShaderGenerator::
@ -527,16 +524,6 @@ synthesize_shader(const RenderState *rs) {
}
if (_lighting) {
text << "\t // Begin model-space light calculations\n";
if (_have_ambient) {
text << "\t float4 tot_ambient = float4(0,0,0,0);\n";
}
if (_have_diffuse) {
text << "\t float4 tot_diffuse = float4(0,0,0,0);\n";
}
if (_have_specular) {
text << "\t float4 tot_specular = float4(0,0,0,0);\n";
}
if (_map_index_normal) {
text << "\t // Translate tangent-space normal in map to model-space.\n";
text << "\t float3 tsnormal = ((float3)tex" << _map_index_normal << " * 2) - 1;\n";
@ -545,14 +532,40 @@ synthesize_shader(const RenderState *rs) {
text << "\t l_normal+= l_binormal * tsnormal.y;\n";
text << "\t l_normal = normalize(l_normal);\n";
} else {
text << "\t // Correct the surface normal for interpolation effects\n";
text << "\t l_normal = normalize(l_normal);\n";
}
text << "\t // Begin model-space light calculations\n";
text << "\t float ldist,lattenv,langle;\n";
text << "\t float4 lcolor,lspec,lvec,lpoint,latten,ldir,leye,lhalf;\n";
if (_separate_ambient_diffuse) {
if (_have_ambient) {
text << "\t float4 tot_ambient = float4(0,0,0,0);\n";
}
if (_have_diffuse) {
text << "\t float4 tot_diffuse = float4(0,0,0,0);\n";
}
} else {
if (_have_ambient || _have_diffuse) {
text << "\t float4 tot_diffuse = float4(0,0,0,0);\n";
}
}
if (_have_specular) {
text << "\t float4 tot_specular = float4(0,0,0,0);\n";
if (_material->has_specular()) {
text << "\t float shininess = attr_material[3].w;\n";
} else {
text << "\t float shininess = 50; // no shininess specified, using default\n";
}
}
for (int i=0; i<(int)_alights.size(); i++) {
text << "\t // Ambient Light " << i << "\n";
text << "\t lcolor = alight_alight" << i << ";\n";
text << "\t tot_ambient += lcolor;\n";
if (_separate_ambient_diffuse) {
text << "\t tot_ambient += lcolor;\n";
} else {
text << "\t tot_diffuse += lcolor;\n";
}
}
for (int i=0; i<(int)_dlights.size(); i++) {
text << "\t // Directional Light " << i << "\n";
@ -567,7 +580,7 @@ synthesize_shader(const RenderState *rs) {
} else {
text << "\t lhalf = dlight_dlight" << i << "_rel_model[3];\n";
}
text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), attr_material[3].w);\n";
text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n";
text << "\t tot_specular += lspec;\n";
}
}
@ -590,7 +603,7 @@ synthesize_shader(const RenderState *rs) {
text << "\t lhalf = normalize(lvec - row1_view_to_model);\n";
}
text << "\t lspec *= lattenv;\n";
text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), attr_material[3].w);\n";
text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n";
text << "\t tot_specular += lspec;\n";
}
}
@ -617,18 +630,47 @@ synthesize_shader(const RenderState *rs) {
text << "\t lhalf = normalize(lvec - row1_view_to_model);\n";
}
text << "\t lspec *= lattenv;\n";
text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), attr_material[3].w);\n";
text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n";
text << "\t tot_specular += lspec;\n";
}
}
switch (_attribs._light_ramp->get_mode()) {
case LightRampAttrib::LRT_identity:
break;
case LightRampAttrib::LRT_single_threshold:
{
float t = _attribs._light_ramp->get_threshold(0);
float l0 = _attribs._light_ramp->get_level(0);
float l1 = _attribs._light_ramp->get_level(1);
text << "\t // Single-threshold light ramp\n";
text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
text << "\t float lr_out = (lr_in < " << t << ") ? " << l0 << ":" << l1 << ";\n";
text << "\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n";
break;
}
case LightRampAttrib::LRT_double_threshold:
{
float t0 = _attribs._light_ramp->get_threshold(0);
float t1 = _attribs._light_ramp->get_threshold(1);
float l0 = _attribs._light_ramp->get_level(0);
float l1 = _attribs._light_ramp->get_level(1);
float l2 = _attribs._light_ramp->get_level(2);
text << "\t // Double-threshold light ramp\n";
text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
text << "\t float lr_out = " << l0 << "\n";
text << "\t if (lr_in > " << t0 << ") lr_out=" << l1 << ";\n";
text << "\t if (lr_in > " << t1 << ") lr_out=" << l2 << ";\n";
text << "\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n";
break;
}
}
text << "\t // Begin model-space light summation\n";
if (_have_emission) {
text << "\t o_color = attr_material[2];\n";
} else {
text << "\t o_color = float4(0,0,0,0);\n";
}
if (_have_ambient) {
if ((_have_ambient)&&(_separate_ambient_diffuse)) {
if (_material->has_ambient()) {
text << "\t o_color += tot_ambient * attr_material[0];\n";
} else if (_vertex_colors) {
@ -669,14 +711,44 @@ synthesize_shader(const RenderState *rs) {
}
for (int i=0; i<_num_textures; i++) {
TextureStage *stage = _attribs._texture->get_on_stage(i);
if ((stage->get_mode() != TextureStage::M_normal)&&
(stage->get_mode() != TextureStage::M_normal_height)) {
switch (stage->get_mode()) {
case TextureStage::M_modulate:
case TextureStage::M_modulate_glow:
case TextureStage::M_modulate_gloss:
text << "\t o_color *= tex" << i << ";\n";
break;
case TextureStage::M_decal:
text << "\t o_color.rgb = lerp(o_color, tex" << i << ", tex" << i << ".a).rgb;\n";
break;
case TextureStage::M_blend:
pgraph_cat.error() << "TextureStage::Mode BLEND not yet supported in per-pixel mode.\n";
break;
case TextureStage::M_replace:
pgraph_cat.error() << "TextureStage::Mode REPLACE not yet supported in per-pixel mode.\n";
break;
case TextureStage::M_add:
text << "\t o_color.rbg = o_color.rgb + tex" << i << ".rgb;\n";
text << "\t o_color.a = o_color.a * tex" << i << ".a;\n";
break;
case TextureStage::M_combine:
pgraph_cat.error() << "TextureStage::Mode COMBINE not yet supported in per-pixel mode.\n";
break;
case TextureStage::M_blend_color_scale:
pgraph_cat.error() << "TextureStage::Mode BLEND_COLOR_SCALE not yet supported in per-pixel mode.\n";
break;
default:
break;
}
}
if (_lighting) {
if (_have_specular) {
text << "\t o_color += tot_specular;\n";
if (_material->has_specular()) {
text << "\t tot_specular *= attr_material[3];\n";
}
if (_map_index_gloss >= 0) {
text << "\t tot_specular *= tex" << _map_index_gloss << ".a;\n";
}
text << "\t o_color.rgb = o_color.rgb + tot_specular.rgb;\n";
}
}
text << "}\n";

View File

@ -110,7 +110,9 @@ protected:
bool _have_diffuse;
bool _have_emission;
bool _have_specular;
bool _separate_ambient_diffuse;
int _map_index_normal;
int _map_index_height;
int _map_index_glow;