mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
Added support for HDR
This commit is contained in:
parent
3882d21189
commit
7bb510a3ef
@ -42,8 +42,9 @@ private:
|
||||
|
||||
PUBLISHED:
|
||||
enum AuxBitplaneOutput {
|
||||
ABO_color = 1, // The usual.
|
||||
ABO_csnormal = 2, // Camera space normal.
|
||||
ABO_color = 1, // Render an ordinary scene into the ordinary color buffer.
|
||||
ABO_csnormal = 2, // Render a camera-space normal into an aux bitplane.
|
||||
ABO_glowalpha = 4, // Render all glow maps into the color buffer alpha channel.
|
||||
};
|
||||
static CPT(RenderAttrib) make();
|
||||
static CPT(RenderAttrib) make(int outputs);
|
||||
|
@ -25,7 +25,7 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE LightRampAttrib::
|
||||
LightRampAttrib() {
|
||||
_mode = LRT_identity;
|
||||
_mode = LRT_default;
|
||||
_level[0] = 0.0;
|
||||
_level[1] = 0.0;
|
||||
_threshold[0] = 0.0;
|
||||
|
@ -26,26 +26,51 @@
|
||||
#include "datagramIterator.h"
|
||||
|
||||
TypeHandle LightRampAttrib::_type_handle;
|
||||
CPT(RenderAttrib) LightRampAttrib::_identity;
|
||||
CPT(RenderAttrib) LightRampAttrib::_default;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LightRampAttrib::make_default
|
||||
// Access: Published, Static
|
||||
// Description: Constructs a new LightRampAttrib object. This
|
||||
// is the standard OpenGL lighting ramp, which clamps
|
||||
// the final light total to the 0-1 range.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightRampAttrib::
|
||||
make_default() {
|
||||
if (_default == 0) {
|
||||
LightRampAttrib *attrib = new LightRampAttrib();
|
||||
_default = return_new(attrib);
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LightRampAttrib::make_identity
|
||||
// Access: Published, Static
|
||||
// Description: Constructs a new LightRampAttrib object.
|
||||
// Description: Constructs a new LightRampAttrib object. This
|
||||
// differs from the usual OpenGL lighting model in that
|
||||
// it does not clamp the final lighting total to (0,1).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightRampAttrib::
|
||||
make_identity() {
|
||||
if (_identity == 0) {
|
||||
LightRampAttrib *attrib = new LightRampAttrib();
|
||||
_identity = return_new(attrib);
|
||||
}
|
||||
return _identity;
|
||||
LightRampAttrib *attrib = new LightRampAttrib();
|
||||
attrib->_mode = LRT_identity;
|
||||
return return_new(attrib);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LightRampAttrib::make_single_threshold
|
||||
// Access: Published, Static
|
||||
// Description: Constructs a new LightRampAttrib object.
|
||||
// Description: Constructs a new LightRampAttrib object. This
|
||||
// causes the luminance of the diffuse lighting
|
||||
// contribution to be quantized using a single threshold:
|
||||
//
|
||||
// if (original_luminance > threshold0) {
|
||||
// luminance = level0;
|
||||
// } else {
|
||||
// luminance = 0.0;
|
||||
// }
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightRampAttrib::
|
||||
make_single_threshold(float thresh0, float val0) {
|
||||
@ -59,7 +84,18 @@ make_single_threshold(float thresh0, float val0) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LightRampAttrib::make_double_threshold
|
||||
// Access: Published, Static
|
||||
// Description: Constructs a new LightRampAttrib object.
|
||||
// Description: Constructs a new LightRampAttrib object. This
|
||||
// causes the luminance of the diffuse lighting
|
||||
// contribution to be quantized using two thresholds:
|
||||
//
|
||||
// if (original_luminance > threshold1) {
|
||||
// luminance = level1;
|
||||
// } else if (original_luminance > threshold0) {
|
||||
// luminance = level0;
|
||||
// } else {
|
||||
// luminance = 0.0;
|
||||
// }
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightRampAttrib::
|
||||
make_double_threshold(float thresh0, float val0, float thresh1, float val1) {
|
||||
@ -72,6 +108,93 @@ make_double_threshold(float thresh0, float val0, float thresh1, float val1) {
|
||||
return return_new(attrib);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LightRampAttrib::make_hdr0
|
||||
// Access: Published, Static
|
||||
// Description: Constructs a new LightRampAttrib object. This causes
|
||||
// an HDR tone mapping operation to be applied.
|
||||
//
|
||||
// Normally, brightness values greater than 1 cannot be
|
||||
// distinguished from each other, causing very brightly lit
|
||||
// objects to wash out white and all detail to be erased.
|
||||
// HDR tone mapping remaps brightness values in the range
|
||||
// 0-infinity into the range (0,1), making it possible to
|
||||
// distinguish detail in scenes whose brightness exceeds 1.
|
||||
//
|
||||
// However, the monitor has finite contrast. Normally, all
|
||||
// of that contrast is used to represent brightnesses in
|
||||
// the range 0-1. The HDR0 tone mapping operator 'steals'
|
||||
// one quarter of that contrast to represent brightnesses in
|
||||
// the range 1-infinity.
|
||||
//
|
||||
// FINAL_RGB = (RGB^3 + RGB^2 + RGB) / (RGB^3 + RGB^2 + RGB + 1)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightRampAttrib::
|
||||
make_hdr0() {
|
||||
LightRampAttrib *attrib = new LightRampAttrib();
|
||||
attrib->_mode = LRT_hdr0;
|
||||
return return_new(attrib);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LightRampAttrib::make_hdr1
|
||||
// Access: Published, Static
|
||||
// Description: Constructs a new LightRampAttrib object. This causes
|
||||
// an HDR tone mapping operation to be applied.
|
||||
//
|
||||
// Normally, brightness values greater than 1 cannot be
|
||||
// distinguished from each other, causing very brightly lit
|
||||
// objects to wash out white and all detail to be erased.
|
||||
// HDR tone mapping remaps brightness values in the range
|
||||
// 0-infinity into the range (0,1), making it possible to
|
||||
// distinguish detail in scenes whose brightness exceeds 1.
|
||||
//
|
||||
// However, the monitor has finite contrast. Normally, all
|
||||
// of that contrast is used to represent brightnesses in
|
||||
// the range 0-1. The HDR1 tone mapping operator 'steals'
|
||||
// one third of that contrast to represent brightnesses in
|
||||
// the range 1-infinity.
|
||||
//
|
||||
// FINAL_RGB = (RGB^2 + RGB) / (RGB^2 + RGB + 1)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightRampAttrib::
|
||||
make_hdr1() {
|
||||
LightRampAttrib *attrib = new LightRampAttrib();
|
||||
attrib->_mode = LRT_hdr1;
|
||||
return return_new(attrib);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LightRampAttrib::make_hdr2
|
||||
// Access: Published, Static
|
||||
// Description: Constructs a new LightRampAttrib object. This causes
|
||||
// an HDR tone mapping operation to be applied.
|
||||
//
|
||||
// Normally, brightness values greater than 1 cannot be
|
||||
// distinguished from each other, causing very brightly lit
|
||||
// objects to wash out white and all detail to be erased.
|
||||
// HDR tone mapping remaps brightness values in the range
|
||||
// 0-infinity into the range (0,1), making it possible to
|
||||
// distinguish detail in scenes whose brightness exceeds 1.
|
||||
//
|
||||
// However, the monitor has finite contrast. Normally, all
|
||||
// of that contrast is used to represent brightnesses in
|
||||
// the range 0-1. The HDR2 tone mapping operator 'steals'
|
||||
// one half of that contrast to represent brightnesses in
|
||||
// the range 1-infinity.
|
||||
//
|
||||
// FINAL_RGB = (RGB) / (RGB + 1)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightRampAttrib::
|
||||
make_hdr2() {
|
||||
LightRampAttrib *attrib = new LightRampAttrib();
|
||||
attrib->_mode = LRT_hdr2;
|
||||
return return_new(attrib);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LightRampAttrib::output
|
||||
// Access: Public, Virtual
|
||||
|
@ -26,16 +26,12 @@ class FactoryParams;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : LightRampAttrib
|
||||
// Description : The LightRampAttrib alters the light level reaching
|
||||
// the surface of the model by applying a "ramp" function.
|
||||
// Typically, this is used for cartoon lighting, in which
|
||||
// case the ramp is a step-function.
|
||||
//
|
||||
// LightRampAttrib is relevant only when lighting and
|
||||
// shader generation are both enabled. Otherwise, it has
|
||||
// no effect. The light ramp only affects the diffuse
|
||||
// contribution. Ambient light is not ramped.
|
||||
//
|
||||
// Description : A Light Ramp is any unary operator that takes a
|
||||
// rendered pixel as input, and adjusts the brightness
|
||||
// of that pixel. For example, gamma correction is a
|
||||
// kind of light ramp. So is HDR tone mapping. So is
|
||||
// cartoon shading. See the constructors for an
|
||||
// explanation of each kind of ramp.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_PGRAPH LightRampAttrib : public RenderAttrib {
|
||||
private:
|
||||
@ -43,14 +39,23 @@ private:
|
||||
|
||||
PUBLISHED:
|
||||
enum LightRampMode {
|
||||
LRT_default,
|
||||
LRT_identity,
|
||||
LRT_single_threshold,
|
||||
LRT_double_threshold,
|
||||
LRT_hdr0,
|
||||
LRT_hdr1,
|
||||
LRT_hdr2,
|
||||
};
|
||||
static CPT(RenderAttrib) make_default();
|
||||
static CPT(RenderAttrib) make_identity();
|
||||
static CPT(RenderAttrib) make_single_threshold(float thresh0, float lev0);
|
||||
static CPT(RenderAttrib) make_double_threshold(float thresh0, float lev0, float thresh1, float lev1);
|
||||
static CPT(RenderAttrib) make_hdr0();
|
||||
static CPT(RenderAttrib) make_hdr1();
|
||||
static CPT(RenderAttrib) make_hdr2();
|
||||
|
||||
|
||||
INLINE LightRampMode get_mode() const;
|
||||
INLINE float get_level(int n) const;
|
||||
INLINE float get_threshold(int n) const;
|
||||
@ -68,7 +73,7 @@ private:
|
||||
float _level[2];
|
||||
float _threshold[2];
|
||||
|
||||
static CPT(RenderAttrib) _identity;
|
||||
static CPT(RenderAttrib) _default;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
|
@ -555,9 +555,7 @@ synthesize_shader(const RenderState *rs) {
|
||||
text << "\t uniform float4 attr_color\n";
|
||||
}
|
||||
text << ") {\n";
|
||||
if (_bitplane_color < 0) {
|
||||
text << "float4 \t o_color;\n";
|
||||
}
|
||||
text << "\t float4 result;\n";
|
||||
text << "\t // Fetch all textures.\n";
|
||||
for (int i=0; i<_num_textures; i++) {
|
||||
text << "\t float4 tex" << i << " = tex2D(tex_" << i << ", float2(l_texcoord" << i << "));\n";
|
||||
@ -680,8 +678,6 @@ synthesize_shader(const RenderState *rs) {
|
||||
}
|
||||
}
|
||||
switch (_attribs._light_ramp->get_mode()) {
|
||||
case LightRampAttrib::LRT_identity:
|
||||
break;
|
||||
case LightRampAttrib::LRT_single_threshold:
|
||||
{
|
||||
float t = _attribs._light_ramp->get_threshold(0);
|
||||
@ -710,60 +706,76 @@ synthesize_shader(const RenderState *rs) {
|
||||
}
|
||||
text << "\t // Begin model-space light summation\n";
|
||||
if (_have_emission) {
|
||||
text << "\t o_color = attr_material[2];\n";
|
||||
if (_map_index_glow >= 0) {
|
||||
text << "\t result = attr_material[2] * tex" << _map_index_glow << ".a;\n";
|
||||
} else {
|
||||
text << "\t result = attr_material[2];\n";
|
||||
}
|
||||
} else {
|
||||
text << "\t o_color = float4(0,0,0,0);\n";
|
||||
if (_map_index_glow >= 0) {
|
||||
text << "\t result = tex" << _map_index_glow << ".aaaa;\n";
|
||||
} else {
|
||||
text << "\t result = float4(0,0,0,0);\n";
|
||||
}
|
||||
}
|
||||
if ((_have_ambient)&&(_separate_ambient_diffuse)) {
|
||||
if (_material->has_ambient()) {
|
||||
text << "\t o_color += tot_ambient * attr_material[0];\n";
|
||||
text << "\t result += tot_ambient * attr_material[0];\n";
|
||||
} else if (_vertex_colors) {
|
||||
text << "\t o_color += tot_ambient * l_color;\n";
|
||||
text << "\t result += tot_ambient * l_color;\n";
|
||||
} else if (_flat_colors) {
|
||||
text << "\t o_color += tot_ambient * attr_color;\n";
|
||||
text << "\t result += tot_ambient * attr_color;\n";
|
||||
} else {
|
||||
text << "\t o_color += tot_ambient;\n";
|
||||
text << "\t result += tot_ambient;\n";
|
||||
}
|
||||
}
|
||||
if (_have_diffuse) {
|
||||
if (_material->has_diffuse()) {
|
||||
text << "\t o_color += tot_diffuse * attr_material[1];\n";
|
||||
text << "\t result += tot_diffuse * attr_material[1];\n";
|
||||
} else if (_vertex_colors) {
|
||||
text << "\t o_color += tot_diffuse * l_color;\n";
|
||||
text << "\t result += tot_diffuse * l_color;\n";
|
||||
} else if (_flat_colors) {
|
||||
text << "\t o_color += tot_diffuse * attr_color;\n";
|
||||
text << "\t result += tot_diffuse * attr_color;\n";
|
||||
} else {
|
||||
text << "\t o_color += tot_diffuse;\n";
|
||||
text << "\t result += tot_diffuse;\n";
|
||||
}
|
||||
}
|
||||
// Use of lerp here is a workaround for a radeon driver bug.
|
||||
if (_vertex_colors) {
|
||||
text << "\t o_color = lerp(o_color, l_color, float4(0,0,0,1));\n";
|
||||
} else if (_flat_colors) {
|
||||
text << "\t o_color = lerp(o_color, attr_color, float4(0,0,0,1));\n";
|
||||
} else {
|
||||
text << "\t o_color.a = lerp(o_color, float4(1,1,1,1), float4(0,0,0,1));\n";
|
||||
if (_attribs._light_ramp->get_mode() == LightRampAttrib::LRT_default) {
|
||||
text << "\t result = saturate(result);\n";
|
||||
}
|
||||
text << "\t // End model-space light calculations\n";
|
||||
|
||||
// Combine in alpha, which bypasses lighting calculations.
|
||||
// Use of lerp here is a workaround for a radeon driver bug.
|
||||
if (_map_index_glow < 0) {
|
||||
if (_vertex_colors) {
|
||||
text << "\t result.a = l_color.a;\n";
|
||||
} else if (_flat_colors) {
|
||||
text << "\t result.a = attr_color.a;\n";
|
||||
} else {
|
||||
text << "\t result.a = 1;\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_vertex_colors) {
|
||||
text << "\t o_color = l_color;\n";
|
||||
text << "\t result = l_color;\n";
|
||||
} else if (_flat_colors) {
|
||||
text << "\t o_color = attr_color;\n";
|
||||
text << "\t result = attr_color;\n";
|
||||
} else {
|
||||
text << "\t o_color = float4(1,1,1,1);\n";
|
||||
text << "\t result = float4(1,1,1,1);\n";
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<_num_textures; i++) {
|
||||
TextureStage *stage = _attribs._texture->get_on_stage(i);
|
||||
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";
|
||||
text << "\t result *= tex" << i << ";\n";
|
||||
break;
|
||||
case TextureStage::M_decal:
|
||||
text << "\t o_color.rgb = lerp(o_color, tex" << i << ", tex" << i << ".a).rgb;\n";
|
||||
text << "\t result.rgb = lerp(result, 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";
|
||||
@ -772,8 +784,8 @@ synthesize_shader(const RenderState *rs) {
|
||||
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";
|
||||
text << "\t result.rbg = result.rgb + tex" << i << ".rgb;\n";
|
||||
text << "\t result.a = result.a * tex" << i << ".a;\n";
|
||||
break;
|
||||
case TextureStage::M_combine:
|
||||
pgraph_cat.error() << "TextureStage::Mode COMBINE not yet supported in per-pixel mode.\n";
|
||||
@ -793,9 +805,26 @@ synthesize_shader(const RenderState *rs) {
|
||||
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 << "\t result.rgb = result.rgb + tot_specular.rgb;\n";
|
||||
}
|
||||
}
|
||||
switch (_attribs._light_ramp->get_mode()) {
|
||||
case LightRampAttrib::LRT_hdr0:
|
||||
text << "\t result.rgb = (result*result*result + result*result + result) / (result*result*result + result*result + result + 1);\n";
|
||||
break;
|
||||
case LightRampAttrib::LRT_hdr1:
|
||||
text << "\t result.rgb = (result*result + result) / (result*result + result + 1);\n";
|
||||
break;
|
||||
case LightRampAttrib::LRT_hdr2:
|
||||
text << "\t result.rgb = result / (result + 1);\n";
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (_bitplane_color >= 0) {
|
||||
// The multiply is a workaround for a radeon driver bug.
|
||||
// It's annoying as heck, since it produces an extra instruction.
|
||||
text << "\t o_color = result * 1.000001;\n";
|
||||
}
|
||||
text << "}\n";
|
||||
|
||||
// Insert the shader into the shader attrib.
|
||||
|
Loading…
x
Reference in New Issue
Block a user