From 914ef2e13d497c0dec444fd82ab80dd08f15de61 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 8 Oct 2018 00:59:22 +0200 Subject: [PATCH] tests: add various unit tests for color-related render states --- tests/display/test_color_buffer.py | 271 +++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 tests/display/test_color_buffer.py diff --git a/tests/display/test_color_buffer.py b/tests/display/test_color_buffer.py new file mode 100644 index 0000000000..dab73cbbb8 --- /dev/null +++ b/tests/display/test_color_buffer.py @@ -0,0 +1,271 @@ +from panda3d import core +import pytest + +TEST_COLOR = core.LColor(1, 127/255.0, 0, 127/255.0) +TEST_COLOR_SCALE = core.LVecBase4(0.5, 0.5, 0.5, 0.5) +TEST_SCALED_COLOR = core.LColor(TEST_COLOR) +TEST_SCALED_COLOR.componentwise_mult(TEST_COLOR_SCALE) +FUZZ = 0.02 + + +@pytest.fixture(scope='session', params=[False, True], ids=["shader:off", "shader:auto"]) +def shader_attrib(request): + """Returns two ShaderAttribs: one with auto shader, one without.""" + if request.param: + return core.ShaderAttrib.make_default().set_shader_auto(True) + else: + return core.ShaderAttrib.make_off() + + +@pytest.fixture(scope='session', params=["mat:off", "mat:empty", "mat:amb", "mat:diff", "mat:both"]) +def material_attrib(request): + """Returns two MaterialAttribs: one with material, one without. It + shouldn't really matter what we set them to, since the tests in here do + not use lighting, and therefore the material should be ignored.""" + + if request.param == "mat:off": + return core.MaterialAttrib.make_off() + + elif request.param == "mat:empty": + return core.MaterialAttrib.make(core.Material()) + + elif request.param == "mat:amb": + mat = core.Material() + mat.ambient = (0.1, 1, 0.5, 1) + return core.MaterialAttrib.make(mat) + + elif request.param == "mat:diff": + mat = core.Material() + mat.diffuse = (0.1, 1, 0.5, 1) + return core.MaterialAttrib.make(mat) + + elif request.param == "mat:both": + mat = core.Material() + mat.diffuse = (0.1, 1, 0.5, 1) + mat.ambient = (0.1, 1, 0.5, 1) + return core.MaterialAttrib.make(mat) + + +@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.""" + + engine = core.GraphicsEngine() + engine.set_threading_model("") + + host_fbprops = core.FrameBufferProperties() + host_fbprops.force_hardware = True + + host = engine.make_output( + graphics_pipe, + 'host', + 0, + host_fbprops, + core.WindowProperties.size(32, 32), + core.GraphicsPipe.BF_refuse_window, + ) + engine.open_windows() + + if host is None: + pytest.skip("GraphicsPipe cannot make offscreen buffers") + + fbprops = core.FrameBufferProperties() + fbprops.force_hardware = True + fbprops.set_rgba_bits(8, 8, 8, 8) + fbprops.srgb_color = request.param + + buffer = engine.make_output( + graphics_pipe, + 'buffer', + 0, + fbprops, + core.WindowProperties.size(32, 32), + core.GraphicsPipe.BF_refuse_window, + host.gsg, + host + ) + engine.open_windows() + + if buffer is None: + pytest.skip("Cannot make color buffer") + + if fbprops.srgb_color != buffer.get_fb_properties().srgb_color: + pytest.skip("Cannot make buffer with required srgb_color setting") + + buffer.set_clear_color_active(True) + buffer.set_clear_color((0, 0, 0, 1)) + + yield buffer.make_display_region() + + if buffer is not None: + engine.remove_window(buffer) + + +def render_color_pixel(region, state, vertex_color=None): + """Renders a fragment using the specified render settings, and returns the + resulting color value.""" + + # Set up the scene with a blank card rendering at specified distance. + scene = core.NodePath("root") + scene.set_attrib(core.DepthTestAttrib.make(core.RenderAttrib.M_always)) + + camera = scene.attach_new_node(core.Camera("camera")) + camera.node().get_lens(0).set_near_far(1, 3) + camera.node().set_cull_bounds(core.OmniBoundingVolume()) + + cm = core.CardMaker("card") + cm.set_frame(-1, 1, -1, 1) + + if vertex_color is not None: + cm.set_color(vertex_color) + + card = scene.attach_new_node(cm.generate()) + card.set_state(state) + card.set_pos(0, 2, 0) + card.set_scale(60) + + region.active = True + region.camera = camera + + color_texture = core.Texture("color") + region.window.add_render_texture(color_texture, + core.GraphicsOutput.RTM_copy_ram, + core.GraphicsOutput.RTP_color) + + region.window.engine.render_frame() + region.window.clear_render_textures() + + col = core.LColor() + color_texture.peek().lookup(col, 0.5, 0.5) + return col + + +def test_color_write_mask(color_region): + state = core.RenderState.make( + core.ColorWriteAttrib.make(core.ColorWriteAttrib.C_green), + ) + result = render_color_pixel(color_region, state) + assert result == (0, 1, 0, 1) + + +def test_color_empty(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result == (1, 1, 1, 1) + + +def test_color_off(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_off(), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result == (1, 1, 1, 1) + + +def test_color_flat(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_flat(TEST_COLOR), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result.almost_equal(TEST_COLOR, FUZZ) + + +def test_color_vertex(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_vertex(), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_COLOR, FUZZ) + + +def test_color_empty_vertex(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_COLOR, FUZZ) + + +def test_color_off_vertex(color_region, shader_attrib, material_attrib): + #XXX This behaviour is really odd. + state = core.RenderState.make( + core.ColorAttrib.make_off(), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_COLOR, FUZZ) + + +def test_scaled_color_empty(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result == (1, 1, 1, 1) + + +def test_scaled_color_off(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_off(), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result == (1, 1, 1, 1) + + +def test_scaled_color_flat(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_flat(TEST_COLOR), + core.ColorScaleAttrib.make(TEST_COLOR_SCALE), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state) + assert result.almost_equal(TEST_SCALED_COLOR, FUZZ) + + +def test_scaled_color_vertex(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorAttrib.make_vertex(), + core.ColorScaleAttrib.make(TEST_COLOR_SCALE), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_SCALED_COLOR, FUZZ) + + +def test_scaled_color_empty_vertex(color_region, shader_attrib, material_attrib): + state = core.RenderState.make( + core.ColorScaleAttrib.make(TEST_COLOR_SCALE), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_SCALED_COLOR, FUZZ) + + +def test_scaled_color_off_vertex(color_region, shader_attrib, material_attrib): + #XXX This behaviour is really odd. + state = core.RenderState.make( + core.ColorAttrib.make_off(), + core.ColorScaleAttrib.make(TEST_COLOR_SCALE), + shader_attrib, + material_attrib, + ) + result = render_color_pixel(color_region, state, vertex_color=TEST_COLOR) + assert result.almost_equal(TEST_SCALED_COLOR, FUZZ) +