From dd77bd4cdff10b97d78208dbb12290fd0519c2b9 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Mon, 17 Aug 2020 03:27:03 -0700 Subject: [PATCH] shadergen: Make use of material alpha if present (#925) The material alpha overrides alpha values from flat color or vertex colors. This follows what the fixed-function pipeline does. Fixes #912 --- panda/src/pgraphnodes/shaderGenerator.cxx | 4 +- tests/display/test_color_buffer.py | 70 +++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index 455f4d4be6..f0e14baa06 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/panda/src/pgraphnodes/shaderGenerator.cxx @@ -1485,7 +1485,9 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { // Combine in alpha, which bypasses lighting calculations. Use of lerp // here is a workaround for a radeon driver bug. if (key._calc_primary_alpha) { - if (key._color_type == ColorAttrib::T_vertex) { + if (key._material_flags & Material::F_diffuse) { + text << "\t result.a = attr_material[1].w;\n"; + } else if (key._color_type == ColorAttrib::T_vertex) { text << "\t result.a = l_color.a;\n"; } else if (key._color_type == ColorAttrib::T_flat) { text << "\t result.a = attr_color.a;\n"; diff --git a/tests/display/test_color_buffer.py b/tests/display/test_color_buffer.py index d95913b0f7..d59b86a0cf 100644 --- a/tests/display/test_color_buffer.py +++ b/tests/display/test_color_buffer.py @@ -46,6 +46,16 @@ def material_attrib(request): return core.MaterialAttrib.make(mat) +@pytest.fixture(scope='session') +def light_attrib(): + light = core.AmbientLight('amb') + light.color = (1, 1, 1, 1) + light_attrib = core.LightAttrib.make() + light_attrib = light_attrib.add_on_light(core.NodePath(light)) + + return light_attrib + + @pytest.fixture(scope='module', params=[False, True], ids=["srgb:off", "srgb:on"]) def color_region(request, graphics_pipe): """Creates and returns a DisplayRegion with a depth buffer.""" @@ -291,3 +301,63 @@ def test_scaled_color_off_vertex(color_region, shader_attrib, material_attrib): result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) assert result.almost_equal(TEST_COLOR_SCALE, FUZZ) + +def test_color_transparency(color_region, shader_attrib, light_attrib): + mat = core.Material() + mat.diffuse = (1, 1, 1, 0.75) + material_attrib = core.MaterialAttrib.make(mat) + + state = core.RenderState.make( + core.TransparencyAttrib.make(core.TransparencyAttrib.M_alpha), + light_attrib, + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result.x == pytest.approx(0.75, 0.1) + + +def test_color_transparency_flat(color_region, shader_attrib, light_attrib): + mat = core.Material() + mat.diffuse = (1, 1, 1, 0.75) + material_attrib = core.MaterialAttrib.make(mat) + + state = core.RenderState.make( + core.TransparencyAttrib.make(core.TransparencyAttrib.M_alpha), + core.ColorAttrib.make_flat(TEST_COLOR), + light_attrib, + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result.x == pytest.approx(0.75, 0.1) + + +def test_color_transparency_vertex(color_region, shader_attrib, light_attrib): + mat = core.Material() + mat.diffuse = (1, 1, 1, 0.75) + material_attrib = core.MaterialAttrib.make(mat) + + state = core.RenderState.make( + core.TransparencyAttrib.make(core.TransparencyAttrib.M_alpha), + core.ColorAttrib.make_vertex(), + light_attrib, + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=(1, 1, 1, 0.5)) + assert result.x == pytest.approx(0.75, 0.1) + + +def test_color_transparency_no_light(color_region, shader_attrib): + mat = core.Material() + mat.diffuse = (1, 1, 1, 0.75) + material_attrib = core.MaterialAttrib.make(mat) + + state = core.RenderState.make( + core.TransparencyAttrib.make(core.TransparencyAttrib.M_alpha), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result.x == pytest.approx(1.0, 0.1)