Enabled shader generator to suppress alphatest and alpha-write

This commit is contained in:
Josh Yelon 2008-05-06 16:27:18 +00:00
parent 33eca53d00
commit 846c2a9fcc
9 changed files with 182 additions and 43 deletions

View File

@ -187,7 +187,7 @@ class CommonFilters:
if (configuration.has_key("Bloom")):
bloomconf = configuration["Bloom"]
intensity = bloomconf.intensity * 3.0
self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw)
self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0)
self.bloom[0].setShaderInput("trigger", bloomconf.mintrigger, 1.0/(bloomconf.maxtrigger-bloomconf.mintrigger), 0.0, 0.0)
self.bloom[0].setShaderInput("desat", bloomconf.desat)
self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity)

View File

@ -3138,16 +3138,19 @@ do_issue_transform() {
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian9::
do_issue_alpha_test() {
const AlphaTestAttrib *attrib = _target._alpha_test;
AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode();
if (mode == AlphaTestAttrib::M_none) {
if (_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) {
set_render_state(D3DRS_ALPHATESTENABLE, FALSE);
} else {
// AlphaTestAttrib::PandaCompareFunc === D3DCMPFUNC
set_render_state(D3DRS_ALPHAFUNC, (D3DCMPFUNC)mode);
set_render_state(D3DRS_ALPHAREF, (UINT) (attrib->get_reference_alpha()*255.0f)); //d3d uses 0x0-0xFF, not a float
set_render_state(D3DRS_ALPHATESTENABLE, TRUE);
const AlphaTestAttrib *attrib = _target._alpha_test;
AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode();
if (mode == AlphaTestAttrib::M_none) {
set_render_state(D3DRS_ALPHATESTENABLE, FALSE);
} else {
// AlphaTestAttrib::PandaCompareFunc === D3DCMPFUNC
set_render_state(D3DRS_ALPHAFUNC, (D3DCMPFUNC)mode);
set_render_state(D3DRS_ALPHAREF, (UINT) (attrib->get_reference_alpha()*255.0f)); //d3d uses 0x0-0xFF, not a float
set_render_state(D3DRS_ALPHATESTENABLE, TRUE);
}
}
}
@ -3453,7 +3456,9 @@ set_state_and_transform(const RenderState *target,
_target._shader = _target_rs->get_generated_shader();
}
if (_target._alpha_test != _state._alpha_test) {
if ((_target._alpha_test != _state._alpha_test)||
(_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test) !=
_state._shader->get_flag(ShaderAttrib::F_subsume_alpha_test))) {
do_issue_alpha_test();
_state._alpha_test = _target._alpha_test;
}
@ -3521,7 +3526,9 @@ set_state_and_transform(const RenderState *target,
if ((_target._transparency != _state._transparency)||
(_target._color_write != _state._color_write)||
(_target._color_blend != _state._color_blend)) {
(_target._color_blend != _state._color_blend)||
(_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) !=
_state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
do_issue_blending();
_state._transparency = _target._transparency;
_state._color_write = _target._color_write;
@ -4085,6 +4092,9 @@ do_issue_blending() {
// to effectively disable color write.
unsigned int color_channels =
_target._color_write->get_channels() & _color_write_mask;
if (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write)) {
color_channels &= ~(ColorWriteAttrib::C_alpha);
}
if (color_channels == ColorWriteAttrib::C_off) {
if (_target._color_write != _state._color_write) {
if (_screen->_can_direct_disable_color_writes) {
@ -4098,7 +4108,9 @@ do_issue_blending() {
}
return;
} else {
if (_target._color_write != _state._color_write) {
if ((_target._color_write != _state._color_write)||
(_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) !=
_state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
if (_screen->_can_direct_disable_color_writes) {
set_render_state(D3DRS_COLORWRITEENABLE, color_channels);
}

View File

@ -272,7 +272,7 @@ rebuild_bitplanes() {
int next = GL_COLOR_ATTACHMENT1_EXT;
for (int i=0; i<_fb_properties.get_aux_rgba(); i++) {
bind_slot(rb_resize, attach, (RenderTexturePlane)(RTP_aux_rgba_0+i), next);
next += 1;
next += 1;
}
for (int i=0; i<_fb_properties.get_aux_hrgba(); i++) {
bind_slot(rb_resize, attach, (RenderTexturePlane)(RTP_aux_hrgba_0+i), next);
@ -339,7 +339,7 @@ bind_slot(bool rb_resize, Texture **attach, RenderTexturePlane slot, GLenum atta
}
}
} else {
// tex->set_format(Texture::F_rgba);
tex->set_format(Texture::F_rgba);
TextureContext *tc = tex->prepare_now(glgsg->get_prepared_objects(), glgsg);
nassertv(tc != (TextureContext *)NULL);
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
@ -412,7 +412,7 @@ bind_slot(bool rb_resize, Texture **attach, RenderTexturePlane slot, GLenum atta
GL_RENDERBUFFER_EXT, rb);
}
} else {
glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_RGBA,
glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_RGBA8_EXT,
_rb_size_x, _rb_size_y);
glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, attachpoint,

View File

@ -3937,14 +3937,18 @@ do_issue_depth_test() {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
do_issue_alpha_test() {
const AlphaTestAttrib *attrib = _target._alpha_test;
AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode();
if (mode == AlphaTestAttrib::M_none) {
if (_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) {
enable_alpha_test(false);
} else {
assert(GL_NEVER==(AlphaTestAttrib::M_never-1+0x200));
GLP(AlphaFunc)(PANDA_TO_GL_COMPAREFUNC(mode), attrib->get_reference_alpha());
enable_alpha_test(true);
const AlphaTestAttrib *attrib = _target._alpha_test;
AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode();
if (mode == AlphaTestAttrib::M_none) {
enable_alpha_test(false);
} else {
assert(GL_NEVER==(AlphaTestAttrib::M_never-1+0x200));
GLP(AlphaFunc)(PANDA_TO_GL_COMPAREFUNC(mode), attrib->get_reference_alpha());
enable_alpha_test(true);
}
}
}
@ -4122,6 +4126,9 @@ do_issue_blending() {
// to effectively disable color write.
unsigned int color_channels =
_target._color_write->get_channels() & _color_write_mask;
if (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write)) {
color_channels &= ~(ColorWriteAttrib::C_alpha);
}
if (color_channels == ColorWriteAttrib::C_off) {
if (_target._color_write != _state._color_write) {
enable_multisample_alpha_one(false);
@ -4137,7 +4144,9 @@ do_issue_blending() {
}
return;
} else {
if (_target._color_write != _state._color_write) {
if ((_target._color_write != _state._color_write)||
(_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) !=
_state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
if (CLP(color_mask)) {
GLP(ColorMask)((color_channels & ColorWriteAttrib::C_red) != 0,
(color_channels & ColorWriteAttrib::C_green) != 0,
@ -4147,6 +4156,7 @@ do_issue_blending() {
}
}
CPT(ColorBlendAttrib) color_blend = _target._color_blend;
ColorBlendAttrib::Mode color_blend_mode = _target._color_blend->get_mode();
TransparencyAttrib::Mode transparency_mode = _target._transparency->get_mode();
@ -6064,7 +6074,9 @@ set_state_and_transform(const RenderState *target,
_target._shader = _target_rs->get_generated_shader();
}
if (_target._alpha_test != _state._alpha_test) {
if ((_target._alpha_test != _state._alpha_test)||
(_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test) !=
_state._shader->get_flag(ShaderAttrib::F_subsume_alpha_test))) {
PStatTimer timer(_draw_set_state_alpha_test_pcollector);
do_issue_alpha_test();
_state._alpha_test = _target._alpha_test;
@ -6138,7 +6150,9 @@ set_state_and_transform(const RenderState *target,
if ((_target._transparency != _state._transparency)||
(_target._color_write != _state._color_write)||
(_target._color_blend != _state._color_blend)) {
(_target._color_blend != _state._color_blend)||
(_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) !=
_state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
PStatTimer timer(_draw_set_state_blending_pcollector);
do_issue_blending();
_state._transparency = _target._transparency;

View File

@ -42,6 +42,8 @@ ShaderAttrib(const ShaderAttrib &copy) :
_shader_priority(copy._shader_priority),
_auto_shader(copy._auto_shader),
_has_shader(copy._has_shader),
_flags(_flags),
_has_flags(_has_flags),
_inputs(copy._inputs)
{
}
@ -79,3 +81,13 @@ get_shader_priority() const {
return _shader_priority;
}
////////////////////////////////////////////////////////////////////
// Function: ShaderAttrib::get_flag
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool ShaderAttrib::
get_flag(int index) const {
return (_flags & (1<<index)) ? true:false;
}

View File

@ -44,6 +44,8 @@ make_off() {
attrib->_shader_priority = 0;
attrib->_auto_shader = false;
attrib->_has_shader = true;
attrib->_flags = 0;
attrib->_has_flags = 0;
_off_attrib = return_new(attrib);
}
return _off_attrib;
@ -64,6 +66,8 @@ make() {
attrib->_shader_priority = 0;
attrib->_auto_shader = false;
attrib->_has_shader = false;
attrib->_flags = 0;
attrib->_has_flags = 0;
_null_attrib = return_new(attrib);
}
return _null_attrib;
@ -129,6 +133,38 @@ clear_shader() const {
return return_new(result);
}
////////////////////////////////////////////////////////////////////
// Function: ShaderAttrib::set_flag
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) ShaderAttrib::
set_flag(int flag, bool value) const {
ShaderAttrib *result = new ShaderAttrib(*this);
int bit = 1<<flag;
if (value) {
result->_flags |= bit;
} else {
result->_flags &= ~bit;
}
result->_has_flags |= bit;
return return_new(result);
}
////////////////////////////////////////////////////////////////////
// Function: ShaderAttrib::clear_flag
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) ShaderAttrib::
clear_flag(int flag) const {
ShaderAttrib *result = new ShaderAttrib(*this);
int bit = 1<<flag;
result->_flags &= ~bit;
result->_has_flags &= ~bit;
return return_new(result);
}
////////////////////////////////////////////////////////////////////
// Function: ShaderAttrib::set_shader_input
// Access: Published
@ -432,6 +468,12 @@ compare_to_impl(const RenderAttrib *other) const {
if (this->_has_shader != that->_has_shader) {
return (this->_has_shader < that->_has_shader) ? -1 : 1;
}
if (this->_flags != that->_flags) {
return (this->_flags < that->_flags) ? -1 : 1;
}
if (this->_has_flags != that->_has_flags) {
return (this->_has_flags < that->_has_flags) ? -1 : 1;
}
Inputs::const_iterator i1 = this->_inputs.begin();
Inputs::const_iterator i2 = that->_inputs.begin();
@ -487,6 +529,10 @@ compose_impl(const RenderAttrib *other) const {
}
}
}
// Update the flags.
attr->_flags &= ~(over->_has_flags);
attr->_flags |= over->_flags;
attr->_has_flags |= (over->_has_flags);
return return_new(attr);
}

View File

@ -40,6 +40,11 @@ PUBLISHED:
static CPT(RenderAttrib) make();
static CPT(RenderAttrib) make_off();
enum {
F_disable_alpha_write = 0, // Suppress writes to color buffer alpha channel.
F_subsume_alpha_test = 1, // Shader promises to subsume the alpha test using TEXKILL
};
INLINE bool has_shader() const;
INLINE bool auto_shader() const;
INLINE int get_shader_priority() const;
@ -59,9 +64,15 @@ PUBLISHED:
CPT(RenderAttrib) set_shader_input(const string &id, const LVector4f &v, int priority=0) const;
CPT(RenderAttrib) set_shader_input(const string &id, double n1=0, double n2=0, double n3=0, double n4=1,
int priority=0) const;
CPT(RenderAttrib) set_flag(int flag, bool value) const;
CPT(RenderAttrib) clear_flag(int flag) const;
CPT(RenderAttrib) clear_shader_input(InternalName *id) const;
CPT(RenderAttrib) clear_shader_input(const string &id) const;
INLINE bool get_flag(int flag) const;
const Shader *get_shader() const;
const ShaderInput *get_shader_input(InternalName *id) const;
const ShaderInput *get_shader_input(const string &id) const;
@ -86,6 +97,8 @@ private:
int _shader_priority;
bool _auto_shader;
bool _has_shader;
int _flags;
int _has_flags;
typedef pmap < CPT(InternalName), CPT(ShaderInput) > Inputs;
Inputs _inputs;

View File

@ -147,32 +147,46 @@ analyze_renderstate(const RenderState *rs) {
// verify_enforce_attrib_lock();
rs->store_into_slots(&_attribs);
int outputs = _attribs._aux_bitplane->get_outputs();
// Check if there's an alpha test, color blend, or transparency.
// Decide whether or not we need alpha testing or alpha blending.
if ((_attribs._alpha_test->get_mode() != RenderAttrib::M_none)&&
(_attribs._alpha_test->get_mode() != RenderAttrib::M_always)) {
_have_alpha_test = true;
}
if (_attribs._color_blend->get_mode() != ColorBlendAttrib::M_none) {
_have_color_blend = true;
_have_alpha_blend = true;
}
if (_attribs._transparency->get_mode() != TransparencyAttrib::M_none) {
_have_transparency = true;
if ((_attribs._transparency->get_mode() == TransparencyAttrib::M_alpha)||
(_attribs._transparency->get_mode() == TransparencyAttrib::M_dual)) {
_have_alpha_blend = true;
}
// Determine what output values are desired.
// Decide what to send to the framebuffer alpha, if anything.
int outputs = _attribs._aux_bitplane->get_outputs();
if (_have_alpha_test || _have_color_blend || _have_transparency) {
_out_primary_alpha = true;
if (outputs & AuxBitplaneAttrib::ABO_glow) {
if (_have_alpha_blend) {
_calc_primary_alpha = true;
_out_primary_glow = false;
_disable_alpha_write = true;
} else if (_have_alpha_test) {
_calc_primary_alpha = true;
_out_primary_glow = true;
_subsume_alpha_test = true;
}
} else {
_out_primary_glow = (outputs & AuxBitplaneAttrib::ABO_glow) ? true:false;
if (_have_alpha_blend || _have_alpha_test) {
_calc_primary_alpha = true;
}
}
// Determine what to put into the aux bitplane.
_out_aux_normal = (outputs & AuxBitplaneAttrib::ABO_aux_normal) ? true:false;
_out_aux_glow = (outputs & AuxBitplaneAttrib::ABO_aux_glow) ? true:false;
_out_aux_any = (_out_aux_normal || _out_aux_glow);
// Count number of textures.
_num_textures = 0;
@ -360,10 +374,11 @@ clear_analysis() {
_map_index_height = -1;
_map_index_glow = -1;
_map_index_gloss = -1;
_calc_primary_alpha = false;
_have_alpha_test = false;
_have_color_blend = false;
_have_transparency = false;
_out_primary_alpha = false;
_have_alpha_blend = false;
_subsume_alpha_test = false;
_disable_alpha_write = false;
_out_primary_glow = false;
_out_aux_normal = false;
_out_aux_glow = false;
@ -795,7 +810,7 @@ synthesize_shader(const RenderState *rs) {
// Combine in alpha, which bypasses lighting calculations.
// Use of lerp here is a workaround for a radeon driver bug.
if (_out_primary_alpha) {
if (_calc_primary_alpha) {
if (_vertex_colors) {
text << "\t result.a = l_color.a;\n";
} else if (_flat_colors) {
@ -833,7 +848,7 @@ synthesize_shader(const RenderState *rs) {
break;
case TextureStage::M_add:
text << "\t result.rbg = result.rgb + tex" << i << ".rgb;\n";
if (_out_primary_alpha) {
if (_calc_primary_alpha) {
text << "\t result.a = result.a * tex" << i << ".a;\n";
}
break;
@ -848,6 +863,20 @@ synthesize_shader(const RenderState *rs) {
}
}
if (_subsume_alpha_test) {
text << "\t // Shader includes alpha test:\n";
double ref = _attribs._alpha_test->get_reference_alpha();
switch (_attribs._alpha_test->get_mode()) {
case RenderAttrib::M_never: text<<"\t discard;\n";
case RenderAttrib::M_less: text<<"\t if (result.a >= "<<ref<<") discard;\n";
case RenderAttrib::M_equal: text<<"\t if (result.a != "<<ref<<") discard;\n";
case RenderAttrib::M_less_equal: text<<"\t if (result.a > "<<ref<<") discard;\n";
case RenderAttrib::M_greater: text<<"\t if (result.a <= "<<ref<<") discard;\n";
case RenderAttrib::M_not_equal: text<<"\t if (result.a == "<<ref<<") discard;\n";
case RenderAttrib::M_greater_equal: text<<"\t if (result.a < "<<ref<<") discard;\n";
}
}
if (_out_primary_glow) {
if (_map_index_glow >= 0) {
text << "\t result.a = tex" << _map_index_glow << ".a;\n";
@ -891,10 +920,22 @@ synthesize_shader(const RenderState *rs) {
// 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";
if (_subsume_alpha_test) {
text << "\t // Shader subsumes normal alpha test.\n";
}
if (_disable_alpha_write) {
text << "\t // Shader disables alpha write.\n";
}
text << "}\n";
// Insert the shader into the shader attrib.
CPT(RenderAttrib) shattr = create_shader_attrib(text.str());
if (_subsume_alpha_test) {
shattr=DCAST(ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_subsume_alpha_test, true);
}
if (_disable_alpha_write) {
shattr=DCAST(ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_disable_alpha_write, true);
}
clear_analysis();
reset_register_allocator();
return shattr;

View File

@ -118,15 +118,16 @@ protected:
int _map_index_glow;
int _map_index_gloss;
bool _out_primary_alpha;
bool _out_primary_glow;
bool _out_aux_normal;
bool _out_aux_glow;
bool _out_aux_any;
bool _have_alpha_test;
bool _have_color_blend;
bool _have_transparency;
bool _have_alpha_blend;
bool _calc_primary_alpha;
bool _subsume_alpha_test;
bool _disable_alpha_write;
bool _need_clipspace_pos;
bool _need_material_props;