Browse Source

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
Mitchell Stokes 5 years ago
parent
commit
dd77bd4cdf
2 changed files with 73 additions and 1 deletions
  1. 3 1
      panda/src/pgraphnodes/shaderGenerator.cxx
  2. 70 0
      tests/display/test_color_buffer.py

+ 3 - 1
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
     // Combine in alpha, which bypasses lighting calculations.  Use of lerp
     // here is a workaround for a radeon driver bug.
     // here is a workaround for a radeon driver bug.
     if (key._calc_primary_alpha) {
     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";
         text << "\t result.a = l_color.a;\n";
       } else if (key._color_type == ColorAttrib::T_flat) {
       } else if (key._color_type == ColorAttrib::T_flat) {
         text << "\t result.a = attr_color.a;\n";
         text << "\t result.a = attr_color.a;\n";

+ 70 - 0
tests/display/test_color_buffer.py

@@ -46,6 +46,16 @@ def material_attrib(request):
         return core.MaterialAttrib.make(mat)
         return core.MaterialAttrib.make(mat)
 
 
 
 
[email protected](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"])
 @pytest.fixture(scope='module', params=[False, True], ids=["srgb:off", "srgb:on"])
 def color_region(request, graphics_pipe):
 def color_region(request, graphics_pipe):
     """Creates and returns a DisplayRegion with a depth buffer."""
     """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)
     result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR)
     assert result.almost_equal(TEST_COLOR_SCALE, FUZZ)
     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)