From 6111c8a108bc59b50a15e4f9ae0bebe7f7c8c19c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 3 Jun 2019 19:11:11 -0700 Subject: [PATCH 01/77] initial work on combining shader variants --- cmake/macros/AutoScribeShader.cmake | 160 +++++++- interface/src/raypick/ParabolaPointer.cpp | 2 +- .../src/RenderableShapeEntityItem.cpp | 9 +- .../src/RenderableWebEntityItem.cpp | 9 +- .../src/entities-renderer/paintStroke.slp | 1 + .../entities-renderer/paintStroke_forward.slp | 1 - .../src/entities-renderer/polyvox.slp | 1 + .../src/entities-renderer/polyvox_fade.slp | 0 .../entities-renderer/src/paintStroke.slf | 30 +- .../entities-renderer/src/paintStroke.slv | 9 +- .../src/paintStroke_forward.slf | 35 -- libraries/entities-renderer/src/polyvox.slf | 130 +++++-- libraries/entities-renderer/src/polyvox.slv | 40 +- .../entities-renderer/src/polyvox_fade.slf | 73 ---- .../entities-renderer/src/polyvox_fade.slv | 33 -- .../render-utils/src/ForwardGlobalLight.slh | 247 ------------ libraries/render-utils/src/GeometryCache.cpp | 75 ++-- libraries/render-utils/src/GeometryCache.h | 10 +- ...eferredGlobalLight.slh => GlobalLight.slh} | 58 ++- .../render-utils/src/RenderPipelines.cpp | 352 +++++++++--------- libraries/render-utils/src/deferred_light.slv | 2 +- libraries/render-utils/src/deformed_model.slv | 56 --- .../render-utils/src/deformed_model_dq.slv | 53 --- .../src/deformed_model_normal_map.slv | 56 --- .../src/deformed_model_normal_map_dq.slv | 57 --- .../src/deformed_model_shadow.slv | 52 --- .../src/deformed_model_shadow_dq.slv | 51 --- .../src/directional_ambient_light.slf | 2 +- .../src/directional_ambient_light_shadow.slf | 2 +- .../src/directional_skybox_light.slf | 2 +- .../src/directional_skybox_light_shadow.slf | 2 +- libraries/render-utils/src/forward_grid.slf | 40 -- .../src/forward_grid_translucent.slf | 41 -- libraries/render-utils/src/forward_model.slf | 83 ----- .../src/forward_model_lightmap.slf | 71 ---- .../src/forward_model_normal_map.slf | 85 ----- .../src/forward_model_normal_map_lightmap.slf | 74 ---- .../src/forward_model_translucent.slf | 81 ---- .../render-utils/src/forward_model_unlit.slf | 42 --- .../render-utils/src/forward_parabola.slf | 18 - .../render-utils/src/forward_sdf_text3D.slf | 57 --- libraries/render-utils/src/forward_simple.slf | 61 --- .../src/forward_simple_textured.slf | 58 --- .../forward_simple_textured_transparent.slf | 60 --- .../src/forward_simple_textured_unlit.slf | 35 -- libraries/render-utils/src/glowLine.slf | 34 -- libraries/render-utils/src/glowLine.slv | 61 --- libraries/render-utils/src/grid.slf | 23 +- .../render-utils/src/grid_translucent.slf | 41 -- libraries/render-utils/src/hmd_ui.slv | 2 +- libraries/render-utils/src/model.slf | 322 ++++++++++++++-- libraries/render-utils/src/model.slv | 106 ++++-- libraries/render-utils/src/model_fade.slf | 73 ---- libraries/render-utils/src/model_lightmap.slf | 50 --- .../render-utils/src/model_lightmap_fade.slf | 59 --- .../src/model_lightmap_normal_map.slf | 55 --- .../src/model_lightmap_normal_map_fade.slf | 64 ---- .../render-utils/src/model_normal_map.slf | 69 ---- .../render-utils/src/model_normal_map.slv | 45 --- .../src/model_normal_map_fade.slf | 78 ---- libraries/render-utils/src/model_shadow.slf | 34 -- libraries/render-utils/src/model_shadow.slv | 42 --- .../render-utils/src/model_shadow_fade.slf | 42 --- .../render-utils/src/model_translucent.slf | 96 ----- .../src/model_translucent_fade.slf | 104 ------ .../src/model_translucent_normal_map.slf | 98 ----- .../src/model_translucent_normal_map_fade.slf | 106 ------ .../src/model_translucent_unlit.slf | 42 --- .../src/model_translucent_unlit_fade.slf | 52 --- libraries/render-utils/src/model_unlit.slf | 45 --- .../render-utils/src/model_unlit_fade.slf | 55 --- libraries/render-utils/src/parabola.slf | 17 +- .../render-utils/src/parabola_translucent.slf | 18 - .../src/render-utils/deformed_model.slp | 2 - .../src/render-utils/deformed_model_dq.slp | 2 - .../src/render-utils/deformed_model_fade.slp | 2 - .../render-utils/deformed_model_fade_dq.slp | 2 - .../deformed_model_normal_map.slp | 2 - .../deformed_model_normal_map_dq.slp | 2 - .../deformed_model_normal_map_fade.slp | 2 - .../deformed_model_normal_map_fade_dq.slp | 2 - .../deformed_model_normal_map_translucent.slp | 2 - ...formed_model_normal_map_translucent_dq.slp | 2 - ...rmed_model_normal_map_translucent_fade.slp | 2 - ...d_model_normal_map_translucent_fade_dq.slp | 2 - .../render-utils/deformed_model_shadow.slp | 2 - .../render-utils/deformed_model_shadow_dq.slp | 2 - .../deformed_model_shadow_fade.slp | 2 - .../deformed_model_shadow_fade_dq.slp | 2 - .../deformed_model_translucent.slp | 2 - .../deformed_model_translucent_dq.slp | 2 - .../deformed_model_translucent_fade.slp | 2 - .../deformed_model_translucent_fade_dq.slp | 2 - .../render-utils/forward_deformed_model.slp | 2 - .../forward_deformed_model_dq.slp | 2 - .../forward_deformed_model_normal_map.slp | 2 - .../forward_deformed_model_normal_map_dq.slp | 2 - .../forward_deformed_translucent.slp | 2 - .../forward_deformed_translucent_dq.slp | 2 - ...orward_deformed_translucent_normal_map.slp | 2 - ...ard_deformed_translucent_normal_map_dq.slp | 2 - .../src/render-utils/forward_grid.slp | 1 - .../render-utils/forward_grid_translucent.slp | 1 - .../src/render-utils/forward_model.slp | 1 - .../render-utils/forward_model_lightmap.slp | 1 - .../render-utils/forward_model_normal_map.slp | 1 - .../forward_model_normal_map_lightmap.slp | 1 - .../forward_model_normal_map_translucent.slp | 2 - .../forward_model_translucent.slp | 1 - .../src/render-utils/forward_model_unlit.slp | 1 - .../src/render-utils/forward_parabola.slp | 1 - .../src/render-utils/forward_sdf_text3D.slp | 1 - .../render-utils/forward_simple_textured.slp | 1 - .../forward_simple_textured_transparent.slp | 1 - .../forward_simple_textured_unlit.slp | 1 - .../src/render-utils/glowLine.slp | 0 .../render-utils/src/render-utils/grid.slp | 1 + .../src/render-utils/grid_translucent.slp | 1 - .../render-utils/src/render-utils/model.slp | 1 + .../src/render-utils/model_fade.slp | 1 - .../src/render-utils/model_lightmap.slp | 1 - .../src/render-utils/model_lightmap_fade.slp | 1 - .../model_lightmap_normal_map.slp | 1 - .../model_lightmap_normal_map_fade.slp | 1 - .../src/render-utils/model_normal_map.slp | 0 .../render-utils/model_normal_map_fade.slp | 1 - .../src/render-utils/model_shadow.slp | 0 .../src/render-utils/model_shadow_fade.slp | 1 - .../src/render-utils/model_translucent.slp | 1 - .../render-utils/model_translucent_fade.slp | 1 - .../model_translucent_normal_map.slp | 1 - .../model_translucent_normal_map_fade.slp | 1 - .../render-utils/model_translucent_unlit.slp | 1 - .../model_translucent_unlit_fade.slp | 1 - .../src/render-utils/model_unlit.slp | 1 - .../src/render-utils/model_unlit_fade.slp | 1 - .../src/render-utils/parabola.slp | 1 + .../src/render-utils/parabola_translucent.slp | 1 - .../src/render-utils/sdf_text3D.slp | 1 + .../render-utils/sdf_text3D_transparent.slp | 1 - .../render-utils/src/render-utils/simple.slp | 1 + .../simple_opaque_web_browser.slp | 1 - .../src/render-utils/simple_procedural.slp | 1 + .../src/render-utils/simple_textured.slp | 1 - .../src/render-utils/simple_textured_fade.slp | 1 - .../render-utils/simple_textured_unlit.slp | 1 - .../simple_textured_unlit_fade.slp | 1 - .../src/render-utils/simple_transparent.slp | 1 - .../simple_transparent_textured.slp | 1 - .../simple_transparent_textured_fade.slp | 1 - .../simple_transparent_textured_unlit.slp | 1 - ...simple_transparent_textured_unlit_fade.slp | 1 - .../simple_transparent_web_browser.slp | 1 - .../src/render-utils/web_browser.slp | 1 + libraries/render-utils/src/sdf_text3D.slf | 70 +++- libraries/render-utils/src/sdf_text3D.slv | 15 +- .../src/sdf_text3D_transparent.slf | 58 --- libraries/render-utils/src/simple.slf | 237 ++++++------ libraries/render-utils/src/simple.slv | 34 +- ..._transparent.slf => simple_procedural.slf} | 72 +++- ...{simple_fade.slv => simple_procedural.slv} | 28 +- .../render-utils/src/simple_textured.slf | 44 --- .../render-utils/src/simple_textured_fade.slf | 66 ---- .../src/simple_textured_unlit.slf | 49 --- .../src/simple_textured_unlit_fade.slf | 61 --- .../src/simple_transparent_textured.slf | 60 --- .../src/simple_transparent_textured_fade.slf | 72 ---- .../src/simple_transparent_textured_unlit.slf | 36 -- ...simple_transparent_textured_unlit_fade.slf | 48 --- .../src/simple_transparent_web_browser.slf | 38 -- libraries/render-utils/src/text/Font.cpp | 4 +- ...opaque_web_browser.slf => web_browser.slf} | 30 +- libraries/render-utils/src/web_browser.slv | 32 ++ tools/shadergen.py | 46 ++- 174 files changed, 1356 insertions(+), 4100 deletions(-) delete mode 100644 libraries/entities-renderer/src/entities-renderer/paintStroke_forward.slp delete mode 100644 libraries/entities-renderer/src/entities-renderer/polyvox_fade.slp delete mode 100644 libraries/entities-renderer/src/paintStroke_forward.slf delete mode 100644 libraries/entities-renderer/src/polyvox_fade.slf delete mode 100644 libraries/entities-renderer/src/polyvox_fade.slv delete mode 100644 libraries/render-utils/src/ForwardGlobalLight.slh rename libraries/render-utils/src/{DeferredGlobalLight.slh => GlobalLight.slh} (86%) delete mode 100644 libraries/render-utils/src/deformed_model.slv delete mode 100644 libraries/render-utils/src/deformed_model_dq.slv delete mode 100644 libraries/render-utils/src/deformed_model_normal_map.slv delete mode 100644 libraries/render-utils/src/deformed_model_normal_map_dq.slv delete mode 100644 libraries/render-utils/src/deformed_model_shadow.slv delete mode 100644 libraries/render-utils/src/deformed_model_shadow_dq.slv delete mode 100644 libraries/render-utils/src/forward_grid.slf delete mode 100644 libraries/render-utils/src/forward_grid_translucent.slf delete mode 100644 libraries/render-utils/src/forward_model.slf delete mode 100644 libraries/render-utils/src/forward_model_lightmap.slf delete mode 100644 libraries/render-utils/src/forward_model_normal_map.slf delete mode 100644 libraries/render-utils/src/forward_model_normal_map_lightmap.slf delete mode 100644 libraries/render-utils/src/forward_model_translucent.slf delete mode 100644 libraries/render-utils/src/forward_model_unlit.slf delete mode 100644 libraries/render-utils/src/forward_parabola.slf delete mode 100644 libraries/render-utils/src/forward_sdf_text3D.slf delete mode 100644 libraries/render-utils/src/forward_simple.slf delete mode 100644 libraries/render-utils/src/forward_simple_textured.slf delete mode 100644 libraries/render-utils/src/forward_simple_textured_transparent.slf delete mode 100644 libraries/render-utils/src/forward_simple_textured_unlit.slf delete mode 100644 libraries/render-utils/src/glowLine.slf delete mode 100644 libraries/render-utils/src/glowLine.slv delete mode 100644 libraries/render-utils/src/grid_translucent.slf delete mode 100644 libraries/render-utils/src/model_fade.slf delete mode 100644 libraries/render-utils/src/model_lightmap.slf delete mode 100644 libraries/render-utils/src/model_lightmap_fade.slf delete mode 100644 libraries/render-utils/src/model_lightmap_normal_map.slf delete mode 100644 libraries/render-utils/src/model_lightmap_normal_map_fade.slf delete mode 100644 libraries/render-utils/src/model_normal_map.slf delete mode 100644 libraries/render-utils/src/model_normal_map.slv delete mode 100644 libraries/render-utils/src/model_normal_map_fade.slf delete mode 100644 libraries/render-utils/src/model_shadow.slf delete mode 100644 libraries/render-utils/src/model_shadow.slv delete mode 100644 libraries/render-utils/src/model_shadow_fade.slf delete mode 100644 libraries/render-utils/src/model_translucent.slf delete mode 100644 libraries/render-utils/src/model_translucent_fade.slf delete mode 100644 libraries/render-utils/src/model_translucent_normal_map.slf delete mode 100644 libraries/render-utils/src/model_translucent_normal_map_fade.slf delete mode 100644 libraries/render-utils/src/model_translucent_unlit.slf delete mode 100644 libraries/render-utils/src/model_translucent_unlit_fade.slf delete mode 100644 libraries/render-utils/src/model_unlit.slf delete mode 100644 libraries/render-utils/src/model_unlit_fade.slf delete mode 100644 libraries/render-utils/src/parabola_translucent.slf delete mode 100644 libraries/render-utils/src/render-utils/deformed_model.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_fade_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_normal_map.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_normal_map_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_normal_map_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_normal_map_fade_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_shadow.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_shadow_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_shadow_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_shadow_fade_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_translucent.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_translucent_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_translucent_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/deformed_model_translucent_fade_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_deformed_model.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_deformed_model_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_deformed_model_normal_map.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_deformed_model_normal_map_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_deformed_translucent.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_deformed_translucent_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map_dq.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_grid.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_grid_translucent.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_model.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_model_lightmap.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_model_normal_map.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_model_normal_map_lightmap.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_model_normal_map_translucent.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_model_translucent.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_model_unlit.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_parabola.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_sdf_text3D.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_simple_textured.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_simple_textured_transparent.slp delete mode 100644 libraries/render-utils/src/render-utils/forward_simple_textured_unlit.slp delete mode 100644 libraries/render-utils/src/render-utils/glowLine.slp delete mode 100644 libraries/render-utils/src/render-utils/grid_translucent.slp delete mode 100644 libraries/render-utils/src/render-utils/model_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/model_lightmap.slp delete mode 100644 libraries/render-utils/src/render-utils/model_lightmap_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/model_lightmap_normal_map.slp delete mode 100644 libraries/render-utils/src/render-utils/model_lightmap_normal_map_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/model_normal_map.slp delete mode 100644 libraries/render-utils/src/render-utils/model_normal_map_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/model_shadow.slp delete mode 100644 libraries/render-utils/src/render-utils/model_shadow_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/model_translucent.slp delete mode 100644 libraries/render-utils/src/render-utils/model_translucent_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/model_translucent_normal_map.slp delete mode 100644 libraries/render-utils/src/render-utils/model_translucent_normal_map_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/model_translucent_unlit.slp delete mode 100644 libraries/render-utils/src/render-utils/model_translucent_unlit_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/model_unlit.slp delete mode 100644 libraries/render-utils/src/render-utils/model_unlit_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/parabola_translucent.slp delete mode 100644 libraries/render-utils/src/render-utils/sdf_text3D_transparent.slp delete mode 100644 libraries/render-utils/src/render-utils/simple_opaque_web_browser.slp create mode 100644 libraries/render-utils/src/render-utils/simple_procedural.slp delete mode 100644 libraries/render-utils/src/render-utils/simple_textured.slp delete mode 100644 libraries/render-utils/src/render-utils/simple_textured_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/simple_textured_unlit.slp delete mode 100644 libraries/render-utils/src/render-utils/simple_textured_unlit_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/simple_transparent.slp delete mode 100644 libraries/render-utils/src/render-utils/simple_transparent_textured.slp delete mode 100644 libraries/render-utils/src/render-utils/simple_transparent_textured_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/simple_transparent_textured_unlit.slp delete mode 100644 libraries/render-utils/src/render-utils/simple_transparent_textured_unlit_fade.slp delete mode 100644 libraries/render-utils/src/render-utils/simple_transparent_web_browser.slp create mode 100644 libraries/render-utils/src/render-utils/web_browser.slp delete mode 100644 libraries/render-utils/src/sdf_text3D_transparent.slf rename libraries/render-utils/src/{simple_transparent.slf => simple_procedural.slf} (79%) rename libraries/render-utils/src/{simple_fade.slv => simple_procedural.slv} (70%) delete mode 100644 libraries/render-utils/src/simple_textured.slf delete mode 100644 libraries/render-utils/src/simple_textured_fade.slf delete mode 100644 libraries/render-utils/src/simple_textured_unlit.slf delete mode 100644 libraries/render-utils/src/simple_textured_unlit_fade.slf delete mode 100644 libraries/render-utils/src/simple_transparent_textured.slf delete mode 100644 libraries/render-utils/src/simple_transparent_textured_fade.slf delete mode 100644 libraries/render-utils/src/simple_transparent_textured_unlit.slf delete mode 100644 libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf delete mode 100644 libraries/render-utils/src/simple_transparent_web_browser.slf rename libraries/render-utils/src/{simple_opaque_web_browser.slf => web_browser.slf} (54%) create mode 100644 libraries/render-utils/src/web_browser.slv diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake index c5bb2b4054..9a18005424 100755 --- a/cmake/macros/AutoScribeShader.cmake +++ b/cmake/macros/AutoScribeShader.cmake @@ -66,6 +66,9 @@ macro(AUTOSCRIBE_PLATFORM_SHADER) list(APPEND SHADER_GEN_LINE ${TEMP_PATH}) file(RELATIVE_PATH TEMP_PATH ${CMAKE_SOURCE_DIR} ${AUTOSCRIBE_OUTPUT_FILE}) list(APPEND SHADER_GEN_LINE ${TEMP_PATH}) + if (NOT("${DEFINES}" STREQUAL "")) + list(APPEND SHADER_GEN_LINE "defines:${DEFINES}") + endif() list(APPEND SHADER_GEN_LINE ${AUTOSCRIBE_SHADER_SEEN_LIBS}) string(CONCAT AUTOSCRIBE_SHADERGEN_COMMANDS "${AUTOSCRIBE_SHADERGEN_COMMANDS}" "${SHADER_GEN_LINE}\n") endmacro() @@ -108,6 +111,10 @@ macro(AUTOSCRIBE_SHADER) set(SHADER_TYPE geom) endif() + if (NOT("${DEFINES}" STREQUAL "")) + string(CONCAT SHADER_NAME "${SHADER_NAME}" "_${DEFINES}") + endif() + set(SCRIBE_ARGS -D GLPROFILE ${GLPROFILE} -T ${SHADER_TYPE} ${SCRIBE_INCLUDES} ) # SHADER_SCRIBED -> the output of scribe @@ -135,11 +142,72 @@ macro(AUTOSCRIBE_SHADER) endif() endif() - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${SHADER_NAME} = ${SHADER_COUNT},\n") + string(CONCAT SHADER_LIST "${SHADER_LIST}" "${SHADER_NAME} = ${SHADER_COUNT},\n") string(CONCAT SHADER_SHADERS_ARRAY "${SHADER_SHADERS_ARRAY}" "${SHADER_COUNT},\n") MATH(EXPR SHADER_COUNT "${SHADER_COUNT}+1") endmacro() +function(GENERATE_DEFINES_LIST_HELPER INPUT_LIST RETURN_LIST) + string(LENGTH "${INPUT_LIST}" STR_LENGTH) + set(OPEN_INDEX -1) + set(STR_INDEX 0) + set(NESTED_DEPTH 0) + while ("${STR_INDEX}" LESS "${STR_LENGTH}") + string(SUBSTRING "${INPUT_LIST}" ${STR_INDEX} 1 CURRENT_CHAR) + + if (("${CURRENT_CHAR}" STREQUAL "(") AND (OPEN_INDEX EQUAL -1)) + set(OPEN_INDEX ${STR_INDEX}) + MATH(EXPR STR_INDEX "${STR_INDEX}+1") + continue() + elseif (("${CURRENT_CHAR}" STREQUAL "(") AND NOT(OPEN_INDEX EQUAL -1)) + MATH(EXPR NESTED_DEPTH "${NESTED_DEPTH}+1") + MATH(EXPR STR_INDEX "${STR_INDEX}+1") + continue() + elseif (("${CURRENT_CHAR}" STREQUAL ")") AND NOT(OPEN_INDEX EQUAL -1) AND (NESTED_DEPTH GREATER 0)) + MATH(EXPR NESTED_DEPTH "${NESTED_DEPTH}-1") + MATH(EXPR STR_INDEX "${STR_INDEX}+1") + continue() + elseif (("${CURRENT_CHAR}" STREQUAL ")") AND NOT(OPEN_INDEX EQUAL -1) AND (NESTED_DEPTH EQUAL 0)) + MATH(EXPR OPEN_INDEX "${OPEN_INDEX}+1") + MATH(EXPR SUBSTR_LENGTH "${STR_INDEX}-${OPEN_INDEX}") + string(SUBSTRING "${INPUT_LIST}" ${OPEN_INDEX} ${SUBSTR_LENGTH} GROUP_STR) + GENERATE_DEFINES_LIST_HELPER("${GROUP_STR}" EXPANDED_GROUP_LIST) + string(REPLACE ";" "/" EXPANDED_GROUP_LIST "${EXPANDED_GROUP_LIST}") + string(REPLACE "(${GROUP_STR})" "${EXPANDED_GROUP_LIST}" INPUT_LIST "${INPUT_LIST}") + MATH(EXPR STR_INDEX "${OPEN_INDEX}-1") + set(OPEN_INDEX -1) + string(LENGTH "${INPUT_LIST}" STR_LENGTH) + continue() + endif() + + MATH(EXPR STR_INDEX "${STR_INDEX}+1") + endwhile() + + list(LENGTH INPUT_LIST NUM_DEFINES) + if (NUM_DEFINES EQUAL 1) + string(REPLACE "/" ";" INPUT_LIST "${INPUT_LIST}") + set(${RETURN_LIST} ${INPUT_LIST} PARENT_SCOPE) + elseif (NUM_DEFINES GREATER 1) + list(GET INPUT_LIST 0 CURRENT_DEFINES) + string(REPLACE "/" ";" CURRENT_DEFINES "${CURRENT_DEFINES}") + list(REMOVE_AT INPUT_LIST 0) + GENERATE_DEFINES_LIST_HELPER("${INPUT_LIST}" REMAINING_DEFINES_LIST) + set(TO_RETURN_LIST "${CURRENT_DEFINES}") + foreach(REMAINING_DEFINES ${REMAINING_DEFINES_LIST}) + list(APPEND TO_RETURN_LIST "${REMAINING_DEFINES}") + foreach(CURRENT_DEFINE ${CURRENT_DEFINES}) + list(APPEND TO_RETURN_LIST "${CURRENT_DEFINE}_${REMAINING_DEFINES}") + endforeach() + endforeach() + set(${RETURN_LIST} ${TO_RETURN_LIST} PARENT_SCOPE) + endif() +endfunction() + +macro(GENERATE_DEFINES_LIST) + set(DEFINES_LIST "") + GENERATE_DEFINES_LIST_HELPER("${ARGV0}" DEFINES_LIST) +endmacro() + macro(AUTOSCRIBE_SHADER_LIB) if (NOT ("${TARGET_NAME}" STREQUAL "shaders")) message(FATAL_ERROR "AUTOSCRIBE_SHADER_LIB can only be used by the shaders library") @@ -164,24 +232,24 @@ macro(AUTOSCRIBE_SHADER_LIB) if (SHADER_VERTEX_FILES) source_group("${SHADER_LIB}/Vertex" FILES ${SHADER_VERTEX_FILES}) list(APPEND ALL_SCRIBE_SHADERS ${SHADER_VERTEX_FILES}) - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace vertex { enum {\n") - foreach(SHADER_FILE ${SHADER_VERTEX_FILES}) + set(SHADER_LIST "namespace vertex { enum {\n") + foreach(SHADER_FILE ${SHADER_VERTEX_FILES}) AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) endforeach() - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "}; } // vertex \n") + set(VERTEX_ENUMS "${SHADER_LIST}") endif() file(GLOB_RECURSE SHADER_FRAGMENT_FILES ${SRC_FOLDER}/*.slf) if (SHADER_FRAGMENT_FILES) source_group("${SHADER_LIB}/Fragment" FILES ${SHADER_FRAGMENT_FILES}) list(APPEND ALL_SCRIBE_SHADERS ${SHADER_FRAGMENT_FILES}) - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace fragment { enum {\n") - foreach(SHADER_FILE ${SHADER_FRAGMENT_FILES}) + set(SHADER_LIST "namespace fragment { enum {\n") + foreach(SHADER_FILE ${SHADER_FRAGMENT_FILES}) AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) endforeach() - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "}; } // fragment \n") + set(FRAGMENT_ENUMS "${SHADER_LIST}") endif() - + # FIXME add support for geometry, compute and tesselation shaders #file(GLOB_RECURSE SHADER_GEOMETRY_FILES ${SRC_FOLDER}/*.slg) #file(GLOB_RECURSE SHADER_COMPUTE_FILES ${SRC_FOLDER}/*.slc) @@ -191,13 +259,13 @@ macro(AUTOSCRIBE_SHADER_LIB) if (SHADER_PROGRAM_FILES) source_group("${SHADER_LIB}/Program" FILES ${SHADER_PROGRAM_FILES}) list(APPEND ALL_SCRIBE_SHADERS ${SHADER_PROGRAM_FILES}) - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace program { enum {\n") + set(PROGRAM_ENUMS "namespace program { enum {\n") foreach(PROGRAM_FILE ${SHADER_PROGRAM_FILES}) get_filename_component(PROGRAM_NAME ${PROGRAM_FILE} NAME_WE) - set(AUTOSCRIBE_PROGRAM_FRAGMENT ${PROGRAM_NAME}) file(READ ${PROGRAM_FILE} PROGRAM_CONFIG) set(AUTOSCRIBE_PROGRAM_VERTEX ${PROGRAM_NAME}) set(AUTOSCRIBE_PROGRAM_FRAGMENT ${PROGRAM_NAME}) + set(AUTOSCRIBE_PROGRAM_DEFINES "") if (NOT("${PROGRAM_CONFIG}" STREQUAL "")) string(REGEX MATCH ".*VERTEX +([_\\:A-Z0-9a-z]+)" MVERT ${PROGRAM_CONFIG}) @@ -208,6 +276,12 @@ macro(AUTOSCRIBE_SHADER_LIB) if (CMAKE_MATCH_1) set(AUTOSCRIBE_PROGRAM_FRAGMENT ${CMAKE_MATCH_1}) endif() + string(REGEX MATCH ".*DEFINES +([a-zA-Z\(\)/: ]+)" MDEF ${PROGRAM_CONFIG}) + if (CMAKE_MATCH_1) + set(AUTOSCRIBE_PROGRAM_DEFINES ${CMAKE_MATCH_1}) + string(TOLOWER AUTOSCRIBE_PROGRAM_DEFINES "${AUTOSCRIBE_PROGRAM_DEFINES}") + string(REGEX REPLACE " +" ";" AUTOSCRIBE_PROGRAM_DEFINES "${AUTOSCRIBE_PROGRAM_DEFINES}") + endif() endif() if (NOT (${AUTOSCRIBE_PROGRAM_VERTEX} MATCHES ".*::.*")) @@ -216,12 +290,72 @@ macro(AUTOSCRIBE_SHADER_LIB) if (NOT (${AUTOSCRIBE_PROGRAM_FRAGMENT} MATCHES ".*::.*")) set(AUTOSCRIBE_PROGRAM_FRAGMENT "fragment::${AUTOSCRIBE_PROGRAM_FRAGMENT}") endif() + string(REGEX REPLACE ".*::" "" VERTEX_NAME "${AUTOSCRIBE_PROGRAM_VERTEX}") + string(REGEX REPLACE ".*::" "" FRAGMENT_NAME "${AUTOSCRIBE_PROGRAM_FRAGMENT}") - set(PROGRAM_ENTRY "${PROGRAM_NAME} = (${AUTOSCRIBE_PROGRAM_VERTEX} << 16) | ${AUTOSCRIBE_PROGRAM_FRAGMENT},\n") - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${PROGRAM_ENTRY}") + GENERATE_DEFINES_LIST("${AUTOSCRIBE_PROGRAM_DEFINES}") + + string(CONCAT PROGRAM_ENUMS "${PROGRAM_ENUMS}" "${PROGRAM_NAME} = (${AUTOSCRIBE_PROGRAM_VERTEX} << 16) | ${AUTOSCRIBE_PROGRAM_FRAGMENT},\n") string(CONCAT SHADER_PROGRAMS_ARRAY "${SHADER_PROGRAMS_ARRAY} ${SHADER_NAMESPACE}::program::${PROGRAM_NAME},\n") + + foreach(DEFINES ${DEFINES_LIST}) + set(ORIG_DEFINES "${DEFINES}") + + string(REPLACE ":v" "" VERTEX_DEFINES "${ORIG_DEFINES}") + string(FIND "${ORIG_DEFINES}" ":f" HAS_FRAGMENT) + if (HAS_FRAGMENT EQUAL -1) + set(DEFINES "${VERTEX_DEFINES}") + set(SHADER_LIST "") + set(SHADER_FILE "${SRC_FOLDER}/${VERTEX_NAME}.slv") + AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) + string(CONCAT VERTEX_ENUMS "${VERTEX_ENUMS}" "${SHADER_LIST}") + else() + string(REGEX REPLACE "_*[^_]*:f" "" VERTEX_DEFINES "${VERTEX_DEFINES}") + endif() + + if (NOT("${VERTEX_DEFINES}" STREQUAL "") AND NOT("${VERTEX_DEFINES}" MATCHES "^_.*")) + set(VERTEX_DEFINES "_${VERTEX_DEFINES}") + endif() + + string(REPLACE ":f" "" FRAGMENT_DEFINES "${ORIG_DEFINES}") + string(FIND "${ORIG_DEFINES}" ":v" HAS_VERTEX) + if (HAS_VERTEX EQUAL -1) + set(DEFINES "${FRAGMENT_DEFINES}") + set(SHADER_LIST "") + set(SHADER_FILE "${SRC_FOLDER}/${FRAGMENT_NAME}.slf") + AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) + string(CONCAT FRAGMENT_ENUMS "${FRAGMENT_ENUMS}" "${SHADER_LIST}") + else() + string(REGEX REPLACE "_*[^_]*:v" "" FRAGMENT_DEFINES "${FRAGMENT_DEFINES}") + endif() + + if (NOT("${FRAGMENT_DEFINES}" STREQUAL "") AND NOT("${FRAGMENT_DEFINES}" MATCHES "^_.*")) + set(FRAGMENT_DEFINES "_${FRAGMENT_DEFINES}") + endif() + + string(REGEX REPLACE ":(f|v)" "" PROGRAM_DEFINES "${ORIG_DEFINES}") + + if (NOT("${PROGRAM_DEFINES}" STREQUAL "")) + string(CONCAT PROGRAM_ENUMS "${PROGRAM_ENUMS}" "${PROGRAM_NAME}_${PROGRAM_DEFINES} = (${AUTOSCRIBE_PROGRAM_VERTEX}${VERTEX_DEFINES} << 16) | ${AUTOSCRIBE_PROGRAM_FRAGMENT}${FRAGMENT_DEFINES},\n") + string(CONCAT SHADER_PROGRAMS_ARRAY "${SHADER_PROGRAMS_ARRAY} ${SHADER_NAMESPACE}::program::${PROGRAM_NAME}_${PROGRAM_DEFINES},\n") + endif() + endforeach() endforeach() - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "}; } // program \n") + endif() + + if (SHADER_VERTEX_FILES) + string(CONCAT VERTEX_ENUMS "${VERTEX_ENUMS}" "}; } // vertex \n") + string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${VERTEX_ENUMS}") + endif() + + if (SHADER_FRAGMENT_FILES) + string(CONCAT FRAGMENT_ENUMS "${FRAGMENT_ENUMS}" "}; } // fragment \n") + string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${FRAGMENT_ENUMS}") + endif() + + if (SHADER_PROGRAM_FILES) + string(CONCAT PROGRAM_ENUMS "${PROGRAM_ENUMS}" "}; } // program \n") + string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${PROGRAM_ENUMS}") endif() # Finish the shader enums diff --git a/interface/src/raypick/ParabolaPointer.cpp b/interface/src/raypick/ParabolaPointer.cpp index 23fc1cb4bd..961ce627a4 100644 --- a/interface/src/raypick/ParabolaPointer.cpp +++ b/interface/src/raypick/ParabolaPointer.cpp @@ -405,7 +405,7 @@ gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabo using namespace shader::render_utils::program; static const std::vector> keys = { - std::make_tuple(false, false, parabola), std::make_tuple(false, true, forward_parabola), std::make_tuple(true, false, parabola_translucent)/*, std::make_tuple(true, true, forward_parabola_translucent)*/ + std::make_tuple(false, false, parabola), std::make_tuple(false, true, parabola_forward), std::make_tuple(true, false, parabola_translucent) }; for (auto& key : keys) { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 6a0d7b001c..ca4154e942 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -30,14 +30,11 @@ using namespace render::entities; // is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down. static const float SPHERE_ENTITY_SCALE = 0.5f; -static_assert(shader::render_utils::program::simple != 0, "Validate simple program exists"); -static_assert(shader::render_utils::program::simple_transparent != 0, "Validate simple transparent program exists"); - ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { - _procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple); + _procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural); // FIXME: Setup proper uniform slots and use correct pipelines for forward rendering - _procedural._opaqueFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple); - _procedural._transparentFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_transparent); + _procedural._opaqueFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_procedural); + _procedural._transparentFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_procedural_translucent); // TODO: move into Procedural.cpp PrepareStencil::testMaskDrawShape(*_procedural._opaqueState); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 3b615ba467..1493792b19 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -314,12 +314,19 @@ void WebEntityRenderer::doRender(RenderArgs* args) { gpu::Batch& batch = *args->_batch; glm::vec4 color; Transform transform; + bool forward; withReadLock([&] { float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; color = glm::vec4(toGlm(_color), _alpha * fadeRatio); color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created); transform = _renderTransform; + forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; }); + + if (color.a == 0.0f) { + return; + } + batch.setResourceTexture(0, _texture); transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); @@ -327,7 +334,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) { // Turn off jitter for these entities batch.pushProjectionJitter(); - DependencyManager::get()->bindWebBrowserProgram(batch, color.a < OPAQUE_ALPHA_THRESHOLD); + DependencyManager::get()->bindWebBrowserProgram(batch, color.a < OPAQUE_ALPHA_THRESHOLD, forward); DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, color, _geometryId); batch.popProjectionJitter(); batch.setResourceTexture(0, nullptr); diff --git a/libraries/entities-renderer/src/entities-renderer/paintStroke.slp b/libraries/entities-renderer/src/entities-renderer/paintStroke.slp index e69de29bb2..e283f4edcb 100644 --- a/libraries/entities-renderer/src/entities-renderer/paintStroke.slp +++ b/libraries/entities-renderer/src/entities-renderer/paintStroke.slp @@ -0,0 +1 @@ +DEFINES forward \ No newline at end of file diff --git a/libraries/entities-renderer/src/entities-renderer/paintStroke_forward.slp b/libraries/entities-renderer/src/entities-renderer/paintStroke_forward.slp deleted file mode 100644 index 4d49e0d3a4..0000000000 --- a/libraries/entities-renderer/src/entities-renderer/paintStroke_forward.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX paintStroke \ No newline at end of file diff --git a/libraries/entities-renderer/src/entities-renderer/polyvox.slp b/libraries/entities-renderer/src/entities-renderer/polyvox.slp index e69de29bb2..82853b2a91 100644 --- a/libraries/entities-renderer/src/entities-renderer/polyvox.slp +++ b/libraries/entities-renderer/src/entities-renderer/polyvox.slp @@ -0,0 +1 @@ +DEFINES (shadow fade)/forward \ No newline at end of file diff --git a/libraries/entities-renderer/src/entities-renderer/polyvox_fade.slp b/libraries/entities-renderer/src/entities-renderer/polyvox_fade.slp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 6ea088751f..2767717772 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -1,10 +1,8 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // -// paintStroke.frag -// fragment shader -// // Created by Eric Levin on 8/10/2015 // Copyright 2015 High Fidelity, Inc. // @@ -12,29 +10,33 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBufferWrite.slh@> +<@if not HIFI_USE_FORWARD@> + <@include DeferredBufferWrite.slh@> +<@else@> + layout(location=0) out vec4 _fragColor0; +<@endif@> <@include paintStroke.slh@> <$declarePolyLineBuffers()$> LAYOUT(binding=0) uniform sampler2D _texture; +<@if not HIFI_USE_FORWARD@> layout(location=0) in vec3 _normalWS; +<@endif@> layout(location=1) in vec2 _texCoord; layout(location=2) in vec4 _color; layout(location=3) in float _distanceFromCenter; void main(void) { vec4 texel = texture(_texture, _texCoord); - int frontCondition = 1 - 2 * int(gl_FrontFacing); - vec3 color = _color.rgb * texel.rgb; - float alpha = texel.a * _color.a; + texel *= _color; + texel.a *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y); - alpha *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y); - - packDeferredFragmentTranslucent( - float(frontCondition) * _normalWS, - alpha, - color, - DEFAULT_ROUGHNESS); +<@if not HIFI_USE_FORWARD@> + float frontCondition = 1.0 - 2.0 * float(gl_FrontFacing); + packDeferredFragmentTranslucent(frontCondition * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS); +<@else@> + _fragColor0 = texel; +<@endif@> } diff --git a/libraries/entities-renderer/src/paintStroke.slv b/libraries/entities-renderer/src/paintStroke.slv index f591370186..2a2025e59f 100644 --- a/libraries/entities-renderer/src/paintStroke.slv +++ b/libraries/entities-renderer/src/paintStroke.slv @@ -1,5 +1,6 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // // paintStroke.vert @@ -20,7 +21,9 @@ <@include paintStroke.slh@> <$declarePolyLineBuffers()$> -layout(location=0) out vec3 _normalWS; +<@if not HIFI_USE_FORWARD@> + layout(location=0) out vec3 _normalWS; +<@endif@> layout(location=1) out vec2 _texCoord; layout(location=2) out vec4 _color; layout(location=3) out float _distanceFromCenter; @@ -50,11 +53,15 @@ void main(void) { vec3 binormalEye = normalize(cross(normalEye, tangentEye)); posEye.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormalEye; <$transformEyeToClipPos(cam, posEye, gl_Position)$> +<@if not HIFI_USE_FORWARD@> <$transformEyeToWorldDir(cam, normalEye, _normalWS)$> +<@endif@> } else { vec3 normal = vertex.normal.xyz; position.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormal; <$transformModelToClipPos(cam, obj, position, gl_Position)$> +<@if not HIFI_USE_FORWARD@> <$transformModelToWorldDir(cam, obj, normal, _normalWS)$> +<@endif@> } } \ No newline at end of file diff --git a/libraries/entities-renderer/src/paintStroke_forward.slf b/libraries/entities-renderer/src/paintStroke_forward.slf deleted file mode 100644 index b949332826..0000000000 --- a/libraries/entities-renderer/src/paintStroke_forward.slf +++ /dev/null @@ -1,35 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// paintStroke.frag -// fragment shader -// -// Created by Eric Levin on 8/10/2015 -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include paintStroke.slh@> -<$declarePolyLineBuffers()$> - -LAYOUT(binding=0) uniform sampler2D _texture; - -layout(location=0) in vec3 _normalWS; -layout(location=1) in vec2 _texCoord; -layout(location=2) in vec4 _color; -layout(location=3) in float _distanceFromCenter; -layout(location=0) out vec4 _fragColor0; - -void main(void) { - vec4 texel = texture(_texture, _texCoord); - int frontCondition = 1 - 2 * int(gl_FrontFacing); - vec3 color = _color.rgb * texel.rgb; - float alpha = texel.a * _color.a; - - alpha *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y); - - _fragColor0 = vec4(color, alpha); -} diff --git a/libraries/entities-renderer/src/polyvox.slf b/libraries/entities-renderer/src/polyvox.slf index 6b1aa25a25..b703a6868c 100644 --- a/libraries/entities-renderer/src/polyvox.slf +++ b/libraries/entities-renderer/src/polyvox.slf @@ -1,8 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> -// polyvox.frag -// fragment shader // // Created by Seth Alves on 2015-8-3 // Copyright 2015 High Fidelity, Inc. @@ -11,51 +10,110 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include graphics/Material.slh@> -<@include DeferredBufferWrite.slh@> -<@include render-utils/ShaderConstants.h@> -<@include entities-renderer/ShaderConstants.h@> +<@if HIFI_USE_FADE@> + <@include Fade.slh@> + <$declareFadeFragment()$> -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normal; -layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _position; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _worldPosition; + layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; +<@endif@> -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap; -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap; -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap; +<@if not HIFI_USE_SHADOW@> + <@include graphics/Material.slh@> + <@include render-utils/ShaderConstants.h@> + <@include entities-renderer/ShaderConstants.h@> -struct PolyvoxParams { - vec4 voxelVolumeSize; -}; + <@if not HIFI_USE_FORWARD@> + <@include DeferredBufferWrite.slh@> + <@else@> + <@include DefaultMaterials.slh@> -LAYOUT(binding=0) uniform polyvoxParamsBuffer { - PolyvoxParams params; -}; + <@include GlobalLight.slh@> + <$declareEvalSkyboxGlobalColor()$> + + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + <@endif@> + + <@if HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; + <@endif@> + layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec3 _positionMS; + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; + layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normalMS; + + LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap; + LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap; + LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap; + + struct PolyvoxParams { + vec4 voxelVolumeSize; + }; + + LAYOUT(binding=0) uniform polyvoxParamsBuffer { + PolyvoxParams params; + }; +<@else@> + layout(location=0) out vec4 _fragColor0; +<@endif@> void main(void) { - vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); - worldNormal = normalize(worldNormal); +<@if HIFI_USE_FADE@> + <@if not HIFI_USE_SHADOW@> + vec3 fadeEmissive; + FadeObjectParams fadeParams; + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _positionWS.xyz, fadeEmissive); + <@else@> + FadeObjectParams fadeParams; + <$fetchFadeObjectParams(fadeParams)$> + applyFadeClip(fadeParams, _positionWS.xyz); + <@endif@> +<@endif@> - float inPositionX = (_worldPosition.x - 0.5) / params.voxelVolumeSize.x; - float inPositionY = (_worldPosition.y - 0.5) / params.voxelVolumeSize.y; - float inPositionZ = (_worldPosition.z - 0.5) / params.voxelVolumeSize.z; +<@if not HIFI_USE_SHADOW@> + float inPositionX = (_positionMS.x - 0.5) / params.voxelVolumeSize.x; + float inPositionY = (_positionMS.y - 0.5) / params.voxelVolumeSize.y; + float inPositionZ = (_positionMS.z - 0.5) / params.voxelVolumeSize.z; vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY)); vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ)); vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY)); - vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z); - vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y); - vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x); - vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0); + vec3 normalMS = normalize(_normalMS); + vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(normalMS.z); + vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(normalMS.y); + vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(normalMS.x); + vec3 diffuse = vec3(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled); - packDeferredFragment( - _normal, - 1.0, - vec3(diffuse), - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); + <@if not HIFI_USE_FORWARD@> + packDeferredFragment( + normalize(_normalWS), + 1.0, + diffuse, + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); + <@else@> + TransformCamera cam = getTransformCamera(); + vec4 color = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + _positionES.xyz, + normalize(_normalWS), + diffuse, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_ROUGHNESS), + 1.0); + <@endif@> +<@else@> + _fragColor0 = vec4(1.0); +<@endif@> } diff --git a/libraries/entities-renderer/src/polyvox.slv b/libraries/entities-renderer/src/polyvox.slv index d17974c994..82ae741888 100644 --- a/libraries/entities-renderer/src/polyvox.slv +++ b/libraries/entities-renderer/src/polyvox.slv @@ -1,8 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> -// polyvox.vert -// vertex shader // // Copyright 2015 High Fidelity, Inc. // @@ -11,20 +10,41 @@ // <@include gpu/Inputs.slh@> -<@include gpu/Transform.slh@> <@include render-utils/ShaderConstants.h@> +<@include gpu/Transform.slh@> <$declareStandardTransform()$> -layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _position; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _worldPosition; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normal; +<@if HIFI_USE_FADE@> + layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; +<@endif@> +<@if not HIFI_USE_SHADOW@> + <@if HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; + <@endif@> + layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec3 _positionMS; + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; + layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; +<@endif@> void main(void) { - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> - _worldPosition = inPosition; + +<@if HIFI_USE_SHADOW@> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> +<@else@> + <@if not HIFI_USE_FORWARD@> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <@else@> + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> + <@endif@> + + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> + _normalMS = inNormal.xyz; + _positionMS = inPosition.xyz; +<@endif@> +<@if HIFI_USE_FADE@> + <$transformModelToWorldPos(obj, inPosition, _positionWS)$> +<@endif@> } diff --git a/libraries/entities-renderer/src/polyvox_fade.slf b/libraries/entities-renderer/src/polyvox_fade.slf deleted file mode 100644 index ae2e05c3dc..0000000000 --- a/libraries/entities-renderer/src/polyvox_fade.slf +++ /dev/null @@ -1,73 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// polyvox_fade.frag -// fragment shader -// -// Created by Olivier Prat on 2017-06-08 -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include graphics/Material.slh@> -<@include DeferredBufferWrite.slh@> -<@include render-utils/ShaderConstants.h@> -<@include entities-renderer/ShaderConstants.h@> - -<@include Fade.slh@> - -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normal; -layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _position; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _worldPosition; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _worldFadePosition; - -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap; -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap; -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap; - -struct PolyvoxParams { - vec4 voxelVolumeSize; -}; - -LAYOUT(binding=0) uniform polyvoxParamsBuffer { - PolyvoxParams params; -}; - -// Declare after all samplers to prevent sampler location mix up with voxel shading (sampler locations are hardcoded in RenderablePolyVoxEntityItem) -<$declareFadeFragment()$> - -void main(void) { - vec3 emissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _worldFadePosition.xyz, emissive); - - vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); - worldNormal = normalize(worldNormal); - - float inPositionX = (_worldPosition.x - 0.5) / params.voxelVolumeSize.x; - float inPositionY = (_worldPosition.y - 0.5) / params.voxelVolumeSize.y; - float inPositionZ = (_worldPosition.z - 0.5) / params.voxelVolumeSize.z; - - vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY)); - vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ)); - vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY)); - - vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z); - vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y); - vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x); - vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0); - - packDeferredFragment( - _normal, - 1.0, - vec3(diffuse), - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE+emissive, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); -} diff --git a/libraries/entities-renderer/src/polyvox_fade.slv b/libraries/entities-renderer/src/polyvox_fade.slv deleted file mode 100644 index 97b98f5840..0000000000 --- a/libraries/entities-renderer/src/polyvox_fade.slv +++ /dev/null @@ -1,33 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// polyvox_fade.vert -// vertex shader -// -// Created by Seth Alves on 2015-8-3 -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Inputs.slh@> -<@include gpu/Transform.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareStandardTransform()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _position; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _worldPosition; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normal; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _worldFadePosition; - -void main(void) { - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> - <$transformModelToWorldPos(obj, inPosition, _worldFadePosition)$> - _worldPosition = inPosition; -} diff --git a/libraries/render-utils/src/ForwardGlobalLight.slh b/libraries/render-utils/src/ForwardGlobalLight.slh deleted file mode 100644 index cf5f070c55..0000000000 --- a/libraries/render-utils/src/ForwardGlobalLight.slh +++ /dev/null @@ -1,247 +0,0 @@ - -<@if not DEFERRED_GLOBAL_LIGHT_SLH@> -<@def DEFERRED_GLOBAL_LIGHT_SLH@> - -<@include graphics/Light.slh@> - -<@include LightingModel.slh@> -<$declareLightBuffer()$> -<$declareLightAmbientBuffer()$> - -<@include LightAmbient.slh@> -<@include LightDirectional.slh@> - -<@func prepareGlobalLight(positionES, normalWS)@> - // prepareGlobalLight - // Transform directions to worldspace - vec3 fragNormalWS = vec3(<$normalWS$>); - vec3 fragPositionWS = vec3(invViewMat * vec4(<$positionES$>, 1.0)); - vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS; - vec3 fragEyeDirWS = normalize(fragEyeVectorWS); - - // Get light - Light light = getKeyLight(); - LightAmbient lightAmbient = getLightAmbient(); - - vec3 lightDirection = getLightDirection(light); - vec3 lightIrradiance = getLightIrradiance(light); - - vec3 color = vec3(0.0); - -<@endfunc@> - - -<@func declareEvalAmbientGlobalColor()@> -vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, float roughness) { - <$prepareGlobalLight(position, normal)$> - color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(lightAmbient); - return color; -} -<@endfunc@> - -<@func declareEvalAmbientSphereGlobalColor(supportScattering)@> - -<$declareLightingAmbient(1, _SCRIBE_NULL, _SCRIBE_NULL, $supportScattering$)$> -<$declareLightingDirectional($supportScattering$)$> - -<@if supportScattering@> -<$declareDeferredCurvature()$> -<@endif@> - -vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, -vec3 albedo, vec3 fresnel, float metallic, float roughness -<@if supportScattering@> - , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature -<@endif@> ) { - - <$prepareGlobalLight(position, normal)$> - - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); - - // Ambient - vec3 ambientDiffuse; - vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance -<@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> ); - color += ambientDiffuse; - color += ambientSpecular; - - - // Directional - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation -<@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> ); - color += directionalDiffuse; - color += directionalSpecular; - - return color; -} - -<@endfunc@> - - -<@func declareEvalSkyboxGlobalColor(supportScattering)@> - -<$declareLightingAmbient(_SCRIBE_NULL, 1, _SCRIBE_NULL, $supportScattering$)$> -<$declareLightingDirectional($supportScattering$)$> - -<@if supportScattering@> -<$declareDeferredCurvature()$> -<@endif@> - -vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, - vec3 albedo, vec3 fresnel, float metallic, float roughness -<@if supportScattering@> - , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature -<@endif@> - ) { - <$prepareGlobalLight(position, normal)$> - - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); - - // Ambient - vec3 ambientDiffuse; - vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance -<@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> - ); - color += ambientDiffuse; - color += ambientSpecular; - - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation -<@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> - ); - color += directionalDiffuse; - color += directionalSpecular; - - // FIXME - temporarily removed until we support it for forward... - // Attenuate the light if haze effect selected - // if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { - // color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); - // } - - return color; -} - -<@endfunc@> - -<@func declareEvalLightmappedColor()@> -vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) { - Light light = getKeyLight(); - LightAmbient ambient = getLightAmbient(); - - // Catch normals perpendicular to the projection plane, hence the magic number for the threshold - // It should be just 0, but we have inaccuracy so we overshoot - const float PERPENDICULAR_THRESHOLD = -0.005; - vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace - float diffuseDot = dot(fragNormal, -getLightDirection(light)); - float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); - - // Reevaluate the shadow attenuation for light facing fragments - float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation; - - // Diffuse light is the lightmap dimmed by shadow - vec3 diffuseLight = lightAttenuation * lightmap; - - // Ambient light is the lightmap when in shadow - vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient); - - return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight); -} -<@endfunc@> - - - -<@include Haze.slh@> - -<@func declareEvalGlobalLightingAlphaBlended()@> - -<$declareLightingAmbient(1, 1, 1)$> -<$declareLightingDirectional()$> - -vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) { - <$prepareGlobalLight(position, normal)$> - - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); - - color += emissive * isEmissiveEnabled(); - - // Ambient - vec3 ambientDiffuse; - vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance); - color += ambientDiffuse; - - // Directional - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); - color += directionalDiffuse; - color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); - - return color; -} - -vec3 evalGlobalLightingAlphaBlendedWithHaze( - mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, - vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) -{ - <$prepareGlobalLight(position, normal)$> - - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); - - color += emissive * isEmissiveEnabled(); - - // Ambient - vec3 ambientDiffuse; - vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance); - color += ambientDiffuse; - - // Directional - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); - color += directionalDiffuse; - color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); - - // Haze - // FIXME - temporarily removed until we support it for forward... - /* if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { - vec4 hazeColor = computeHazeColor( - positionES, // fragment position in eye coordinates - fragPositionWS, // fragment position in world coordinates - invViewMat[3].xyz, // eye position in world coordinates - lightDirection // keylight direction vector - ); - - color = mix(color.rgb, hazeColor.rgb, hazeColor.a); - }*/ - - return color; -} - -<@endfunc@> - - -<@endif@> diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 7bd6f88d71..3cc43eaa76 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -113,6 +113,7 @@ static const uint SHAPE_NORMALS_OFFSET = offsetof(GeometryCache::ShapeVertex, no static const uint SHAPE_TEXCOORD0_OFFSET = offsetof(GeometryCache::ShapeVertex, uv); static const uint SHAPE_TANGENT_OFFSET = offsetof(GeometryCache::ShapeVertex, tangent); +std::map, gpu::PipelinePointer> GeometryCache::_webPipelines; std::map, gpu::PipelinePointer> GeometryCache::_gridPipelines; void GeometryCache::computeSimpleHullPointListForShape(const int entityShape, const glm::vec3 &entityExtents, QVector &outPointList) { @@ -2045,7 +2046,7 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo const float DEPTH_BIAS = 0.001f; static const std::vector> keys = { - std::make_tuple(false, false, grid), std::make_tuple(false, true, forward_grid), std::make_tuple(true, false, grid_translucent), std::make_tuple(true, true, forward_grid_translucent) + std::make_tuple(false, false, grid), std::make_tuple(false, true, grid_forward), std::make_tuple(true, false, grid_translucent), std::make_tuple(true, true, grid_translucent_forward) }; for (auto& key : keys) { @@ -2136,34 +2137,36 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) { return a.getRaw() == b.getRaw(); } -static void buildWebShader(int programId, bool blendEnable, - gpu::ShaderPointer& shaderPointerOut, gpu::PipelinePointer& pipelinePointerOut) { - shaderPointerOut = gpu::Shader::createProgram(programId); - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_NONE); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - state->setBlendFunction(blendEnable, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - - PrepareStencil::testMaskDrawShapeNoAA(*state); - - pipelinePointerOut = gpu::Pipeline::create(shaderPointerOut, state); +void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward) { + batch.setPipeline(getWebBrowserProgram(transparent, forward)); } -void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent) { - batch.setPipeline(getWebBrowserProgram(transparent)); -} +gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent, bool forward) { + if (_webPipelines.empty()) { + using namespace shader::render_utils::program; + static const std::vector> keys = { + std::make_tuple(false, false, web_browser), std::make_tuple(false, true, web_browser_forward), + std::make_tuple(true, false, web_browser_translucent) + }; -gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent) { - static std::once_flag once; - std::call_once(once, [&]() { - // FIXME: need a forward pipeline for this - buildWebShader(shader::render_utils::program::simple_opaque_web_browser, false, _simpleOpaqueWebBrowserShader, _simpleOpaqueWebBrowserPipeline); - buildWebShader(shader::render_utils::program::simple_transparent_web_browser, true, _simpleTransparentWebBrowserShader, _simpleTransparentWebBrowserPipeline); - }); + for (auto& key : keys) { + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + // FIXME: do we need a testMaskDrawNoAA? + PrepareStencil::testMaskDrawShapeNoAA(*state); + state->setBlendFunction(std::get<0>(key), + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + state->setCullMode(gpu::State::CULL_NONE); - return transparent ? _simpleTransparentWebBrowserPipeline : _simpleOpaqueWebBrowserPipeline; + _webPipelines[{std::get<0>(key), std::get<1>(key)}] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state); + } + + // The forward opaque/translucent pipelines are the same for now + _webPipelines[{ true, true }] = _webPipelines[{ false, true }]; + } + + return _webPipelines[{ transparent, forward }]; } void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool isAntiAliased, bool forward) { @@ -2191,24 +2194,24 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp std::call_once(once, [&]() { using namespace shader::render_utils::program; - _forwardSimpleShader = gpu::Shader::createProgram(forward_simple_textured); - _forwardTransparentShader = gpu::Shader::createProgram(forward_simple_textured_transparent); - _forwardUnlitShader = gpu::Shader::createProgram(forward_simple_textured_unlit); + _forwardSimpleShader = gpu::Shader::createProgram(simple_forward); + _forwardTransparentShader = gpu::Shader::createProgram(simple_translucent_forward); + _forwardUnlitShader = gpu::Shader::createProgram(simple_unlit_forward); - _simpleShader = gpu::Shader::createProgram(simple_textured); - _transparentShader = gpu::Shader::createProgram(simple_transparent_textured); - _unlitShader = gpu::Shader::createProgram(simple_textured_unlit); + _simpleShader = gpu::Shader::createProgram(simple); + _transparentShader = gpu::Shader::createProgram(simple_translucent); + _unlitShader = gpu::Shader::createProgram(simple_unlit); }); } else { static std::once_flag once; std::call_once(once, [&]() { using namespace shader::render_utils::program; - // FIXME: these aren't right... - _forwardSimpleFadeShader = gpu::Shader::createProgram(forward_simple_textured); - _forwardUnlitFadeShader = gpu::Shader::createProgram(forward_simple_textured_unlit); + // Fading is currently disabled during forward rendering + _forwardSimpleFadeShader = gpu::Shader::createProgram(simple_forward); + _forwardUnlitFadeShader = gpu::Shader::createProgram(simple_unlit_forward); - _simpleFadeShader = gpu::Shader::createProgram(simple_textured_fade); - _unlitFadeShader = gpu::Shader::createProgram(simple_textured_unlit_fade); + _simpleFadeShader = gpu::Shader::createProgram(simple_fade); + _unlitFadeShader = gpu::Shader::createProgram(simple_unlit_fade); }); } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index a42b059a8c..31e1eddc3d 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -176,8 +176,9 @@ public: static gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true, bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true, bool forward = false); - void bindWebBrowserProgram(gpu::Batch& batch, bool transparent = false); - gpu::PipelinePointer getWebBrowserProgram(bool transparent); + void bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward); + gpu::PipelinePointer getWebBrowserProgram(bool transparent, bool forward); + static std::map, gpu::PipelinePointer> _webPipelines; static void initializeShapePipelines(); @@ -477,11 +478,6 @@ private: static QHash _simplePrograms; - gpu::ShaderPointer _simpleOpaqueWebBrowserShader; - gpu::PipelinePointer _simpleOpaqueWebBrowserPipeline; - gpu::ShaderPointer _simpleTransparentWebBrowserShader; - gpu::PipelinePointer _simpleTransparentWebBrowserPipeline; - static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true, bool unlit = false, bool depthBias = false, bool forward = false); static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool culled = true, diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/GlobalLight.slh similarity index 86% rename from libraries/render-utils/src/DeferredGlobalLight.slh rename to libraries/render-utils/src/GlobalLight.slh index 03ec18c321..1cc357fe5f 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/GlobalLight.slh @@ -8,8 +8,8 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html !> -<@if not DEFERRED_GLOBAL_LIGHT_SLH@> -<@def DEFERRED_GLOBAL_LIGHT_SLH@> +<@if not GLOBAL_LIGHT_SLH@> +<@def GLOBAL_LIGHT_SLH@> <@include graphics/Light.slh@> @@ -43,7 +43,6 @@ <@endfunc@> - <@func declareEvalAmbientGlobalColor()@> vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, float roughness) { <$prepareGlobalLight(position, normal)$> @@ -62,10 +61,11 @@ vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obsc <@endif@> vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, -vec3 albedo, vec3 fresnel, float metallic, float roughness + vec3 albedo, vec3 fresnel, float metallic, float roughness <@if supportScattering@> , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature -<@endif@> ) { +<@endif@> + ) { <$prepareGlobalLight(position, normal)$> @@ -76,19 +76,20 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness vec3 ambientSpecular; evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance <@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> ); + , scattering, midNormalCurvature, lowNormalCurvature +<@endif@> + ); color += ambientDiffuse; color += ambientSpecular; - // Directional vec3 directionalDiffuse; vec3 directionalSpecular; evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation <@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> ); + , scattering, midNormalCurvature, lowNormalCurvature +<@endif@> + ); color += directionalDiffuse; color += directionalSpecular; @@ -97,7 +98,9 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness <@endfunc@> +<@if not HIFI_USE_FORWARD@> <@include Haze.slh@> +<@endif@> <@func declareEvalSkyboxGlobalColor(supportScattering)@> @@ -123,7 +126,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu vec3 ambientSpecular; evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance <@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature + , scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); color += ambientDiffuse; @@ -133,16 +136,18 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu vec3 directionalSpecular; evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation <@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature + , scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); color += directionalDiffuse; color += directionalSpecular; +<@if not HIFI_USE_FORWARD@> // Attenuate the light if haze effect selected if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); } +<@endif@> return color; } @@ -179,6 +184,29 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur <$declareLightingAmbient(1, 1, 1)$> <$declareLightingDirectional()$> +vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) { + <$prepareGlobalLight(position, normal)$> + + SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); + + color += emissive * isEmissiveEnabled(); + + // Ambient + vec3 ambientDiffuse; + vec3 ambientSpecular; + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance); + color += ambientDiffuse; + + // Directional + vec3 directionalDiffuse; + vec3 directionalSpecular; + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); + color += directionalDiffuse; + color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); + + return color; +} + vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity, vec3 prevLighting) { <$prepareGlobalLight(position, normal)$> @@ -202,6 +230,7 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl return color; } + <@endfunc@> <@func declareEvalGlobalLightingAlphaBlendedWithHaze()@> @@ -213,7 +242,6 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) { - <$prepareGlobalLight(positionES, normalWS)$> SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); @@ -233,6 +261,7 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( color += directionalDiffuse; color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); +<@if not HIFI_USE_FORWARD@> // Haze if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { vec4 hazeColor = computeHazeColor( @@ -244,6 +273,7 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( color = mix(color.rgb, hazeColor.rgb, hazeColor.a); } +<@endif@> return color; } @@ -270,6 +300,7 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( color += ambientDiffuse + directionalDiffuse; color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); +<@if not HIFI_USE_FORWARD@> // Haze if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { vec4 hazeColor = computeHazeColor( @@ -281,6 +312,7 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( color = mix(color.rgb, hazeColor.rgb, hazeColor.a); } +<@endif@> return color; } diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 2817abb4a1..20fb4c6d31 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -54,158 +54,125 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip using namespace shader::render_utils::program; using Key = render::ShapeKey; auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4); - // TODO: Refactor this to use a filter - // Opaques - addPipeline( - Key::Builder().withMaterial(), - model, nullptr, nullptr); - addPipeline( - Key::Builder(), - simple_textured, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withUnlit(), - model_unlit, nullptr, nullptr); - addPipeline( - Key::Builder().withUnlit(), - simple_textured_unlit, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withTangents(), - model_normal_map, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withFade(), - model_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withFade(), - simple_textured_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withUnlit().withFade(), - model_unlit_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withUnlit().withFade(), - simple_textured_unlit_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withTangents().withFade(), - model_normal_map_fade, batchSetter, itemSetter); + // TOOD: build this list algorithmically so we don't have to maintain it + std::vector> pipelines = { + // Simple + { Key::Builder(), simple }, + { Key::Builder().withTranslucent(), simple_translucent }, + { Key::Builder().withUnlit(), simple_unlit }, + { Key::Builder().withTranslucent().withUnlit(), simple_translucent_unlit }, + // Simple Fade + { Key::Builder().withFade(), simple_fade }, + { Key::Builder().withTranslucent().withFade(), simple_translucent_fade }, + { Key::Builder().withUnlit().withFade(), simple_unlit_fade }, + { Key::Builder().withTranslucent().withUnlit().withFade(), simple_translucent_unlit_fade }, - // Translucents - addPipeline( - Key::Builder().withMaterial().withTranslucent(), - model_translucent, nullptr, nullptr); - addPipeline( - Key::Builder().withTranslucent(), - simple_transparent_textured, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withUnlit(), - model_translucent_unlit, nullptr, nullptr); - addPipeline( - Key::Builder().withTranslucent().withUnlit(), - simple_transparent_textured_unlit, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withTangents(), - model_translucent_normal_map, nullptr, nullptr); - addPipeline( - // FIXME: Ignore lightmap for translucents meshpart - Key::Builder().withMaterial().withTranslucent().withLightmap(), - model_translucent, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withTranslucent().withFade(), - model_translucent_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withTranslucent().withFade(), - simple_transparent_textured_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withUnlit().withFade(), - model_translucent_unlit_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withTranslucent().withUnlit().withFade(), - simple_transparent_textured_unlit_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withTangents().withFade(), - model_translucent_normal_map_fade, batchSetter, itemSetter); - addPipeline( - // FIXME: Ignore lightmap for translucents meshpart - Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(), - model_translucent_fade, batchSetter, itemSetter); - // Lightmapped - addPipeline( - Key::Builder().withMaterial().withLightmap(), - model_lightmap, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withLightmap().withTangents(), - model_lightmap_normal_map, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withLightmap().withFade(), - model_lightmap_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withLightmap().withTangents().withFade(), - model_lightmap_normal_map_fade, batchSetter, itemSetter); + // Unskinned + { Key::Builder().withMaterial(), model }, + { Key::Builder().withMaterial().withTangents(), model_normalmap }, + { Key::Builder().withMaterial().withTranslucent(), model_translucent }, + { Key::Builder().withMaterial().withTangents().withTranslucent(), model_normalmap_translucent }, + // Unskinned Unlit + { Key::Builder().withMaterial().withUnlit(), model_unlit }, + { Key::Builder().withMaterial().withTangents().withUnlit(), model_normalmap_unlit }, + { Key::Builder().withMaterial().withTranslucent().withUnlit(), model_translucent_unlit }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit(), model_normalmap_translucent_unlit }, + // Unskinned Lightmapped + { Key::Builder().withMaterial().withLightmap(), model_lightmap }, + { Key::Builder().withMaterial().withTangents().withLightmap(), model_normalmap_lightmap }, + { Key::Builder().withMaterial().withTranslucent().withLightmap(), model_translucent_lightmap }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightmap(), model_normalmap_translucent_lightmap }, + // Unskinned Fade + { Key::Builder().withMaterial().withFade(), model_fade }, + { Key::Builder().withMaterial().withTangents().withFade(), model_normalmap_fade }, + { Key::Builder().withMaterial().withTranslucent().withFade(), model_translucent_fade }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withFade(), model_normalmap_translucent_fade }, + // Unskinned Unlit Fade + { Key::Builder().withMaterial().withUnlit().withFade(), model_unlit_fade }, + { Key::Builder().withMaterial().withTangents().withUnlit().withFade(), model_normalmap_unlit_fade }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withFade(), model_translucent_unlit_fade }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withFade(), model_normalmap_translucent_unlit_fade }, + // Unskinned Lightmapped Fade + { Key::Builder().withMaterial().withLightmap().withFade(), model_lightmap_fade }, + { Key::Builder().withMaterial().withTangents().withLightmap().withFade(), model_normalmap_lightmap_fade }, + { Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(), model_translucent_lightmap_fade }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightmap().withFade(), model_normalmap_translucent_lightmap_fade }, - // matrix palette skinned - addPipeline( - Key::Builder().withMaterial().withDeformed(), - deformed_model, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withDeformed().withTangents(), - deformed_model_normal_map, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withDeformed().withFade(), - deformed_model_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withDeformed().withTangents().withFade(), - deformed_model_normal_map_fade, batchSetter, itemSetter); - // matrix palette skinned and translucent - addPipeline( - Key::Builder().withMaterial().withDeformed().withTranslucent(), - deformed_model_translucent, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withDeformed().withTranslucent().withTangents(), - deformed_model_normal_map_translucent, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withDeformed().withTranslucent().withFade(), - deformed_model_translucent_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withDeformed().withTranslucent().withTangents().withFade(), - deformed_model_normal_map_translucent_fade, batchSetter, itemSetter); + // Matrix palette skinned + { Key::Builder().withMaterial().withDeformed(), model_deformed }, + { Key::Builder().withMaterial().withTangents().withDeformed(), model_normalmap_deformed }, + { Key::Builder().withMaterial().withTranslucent().withDeformed(), model_translucent_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withDeformed(), model_normalmap_translucent_deformed }, + // Matrix palette skinned Unlit + { Key::Builder().withMaterial().withUnlit().withDeformed(), model_unlit_deformed }, + { Key::Builder().withMaterial().withTangents().withUnlit().withDeformed(), model_normalmap_unlit_deformed }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withDeformed(), model_translucent_unlit_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withDeformed(), model_normalmap_translucent_unlit_deformed }, + // Matrix palette skinned Lightmapped + { Key::Builder().withMaterial().withLightmap().withDeformed(), model_lightmap_deformed }, + { Key::Builder().withMaterial().withTangents().withLightmap().withDeformed(), model_normalmap_lightmap_deformed }, + { Key::Builder().withMaterial().withTranslucent().withLightmap().withDeformed(), model_translucent_lightmap_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightmap().withDeformed(), model_normalmap_translucent_lightmap_deformed }, + // Matrix palette skinned Fade + { Key::Builder().withMaterial().withFade().withDeformed(), model_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withFade().withDeformed(), model_normalmap_fade_deformed }, + { Key::Builder().withMaterial().withTranslucent().withFade().withDeformed(), model_translucent_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withFade().withDeformed(), model_normalmap_translucent_fade_deformed }, + // Matrix palette skinned Unlit Fade + { Key::Builder().withMaterial().withUnlit().withFade().withDeformed(), model_unlit_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withUnlit().withFade().withDeformed(), model_normalmap_unlit_fade_deformed }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withFade().withDeformed(), model_translucent_unlit_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withFade().withDeformed(), model_normalmap_translucent_unlit_fade_deformed }, + // Matrix palette skinned Lightmapped Fade + { Key::Builder().withMaterial().withLightmap().withFade().withDeformed(), model_lightmap_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withLightmap().withFade().withDeformed(), model_normalmap_lightmap_fade_deformed }, + { Key::Builder().withMaterial().withTranslucent().withLightmap().withFade().withDeformed(), model_translucent_lightmap_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightmap().withFade().withDeformed(), model_normalmap_translucent_lightmap_fade_deformed }, - // dual quaternion skinned - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned(), - deformed_model_dq, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTangents(), - deformed_model_normal_map_dq, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withFade(), - deformed_model_fade_dq, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTangents().withFade(), - deformed_model_normal_map_fade_dq, batchSetter, itemSetter); - // dual quaternion skinned and translucent - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTranslucent(), - deformed_model_translucent_dq, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTranslucent().withTangents(), - deformed_model_normal_map_translucent_dq, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTranslucent().withFade(), - deformed_model_translucent_fade_dq, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTranslucent().withTangents().withFade(), - deformed_model_normal_map_translucent_fade_dq, batchSetter, itemSetter); + // Dual quaternion skinned + { Key::Builder().withMaterial().withDeformed().withDualQuatSkinned(), model_deformeddq }, + { Key::Builder().withMaterial().withTangents().withDeformed().withDualQuatSkinned(), model_normalmap_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withDeformed().withDualQuatSkinned(), model_translucent_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_deformeddq }, + // Dual quaternion skinned Unlit + { Key::Builder().withMaterial().withUnlit().withDeformed().withDualQuatSkinned(), model_unlit_deformeddq }, + { Key::Builder().withMaterial().withTangents().withUnlit().withDeformed().withDualQuatSkinned(), model_normalmap_unlit_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withDeformed().withDualQuatSkinned(), model_translucent_unlit_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_unlit_deformeddq }, + // Dual quaternion skinned Lightmapped + { Key::Builder().withMaterial().withLightmap().withDeformed().withDualQuatSkinned(), model_lightmap_deformeddq }, + { Key::Builder().withMaterial().withTangents().withLightmap().withDeformed().withDualQuatSkinned(), model_normalmap_lightmap_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withLightmap().withDeformed().withDualQuatSkinned(), model_translucent_lightmap_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightmap().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_lightmap_deformeddq }, + // Dual quaternion skinned Fade + { Key::Builder().withMaterial().withFade().withDeformed().withDualQuatSkinned(), model_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_fade_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withFade().withDeformed().withDualQuatSkinned(), model_translucent_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_fade_deformeddq }, + // Dual quaternion skinned Unlit Fade + { Key::Builder().withMaterial().withUnlit().withFade().withDeformed().withDualQuatSkinned(), model_unlit_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withUnlit().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_unlit_fade_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withFade().withDeformed().withDualQuatSkinned(), model_translucent_unlit_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_unlit_fade_deformeddq }, + // Dual quaternion skinned Lightmapped Fade + { Key::Builder().withMaterial().withLightmap().withFade().withDeformed().withDualQuatSkinned(), model_lightmap_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withLightmap().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_lightmap_fade_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withLightmap().withFade().withDeformed().withDualQuatSkinned(), model_translucent_lightmap_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightmap().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_lightmap_fade_deformeddq }, + }; + + for (auto& pipeline : pipelines) { + if (pipeline.first.build().isFaded()) { + addPipeline(pipeline.first, pipeline.second, batchSetter, itemSetter); + } else { + addPipeline(pipeline.first, pipeline.second, nullptr, nullptr); + } + } } void initForwardPipelines(ShapePlumber& plumber) { - using namespace shader::render_utils; - + using namespace shader::render_utils::program; using Key = render::ShapeKey; auto addPipelineBind = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4); @@ -218,38 +185,66 @@ void initForwardPipelines(ShapePlumber& plumber) { // Forward pipelines need the lightBatchSetter for opaques and transparents forceLightBatchSetter = true; - // Simple Opaques - addPipeline(Key::Builder(), program::forward_simple_textured); - addPipeline(Key::Builder().withUnlit(), program::forward_simple_textured_unlit); + // TOOD: build this list algorithmically so we don't have to maintain it + std::vector> pipelines = { + // Simple + { Key::Builder(), simple_forward }, + { Key::Builder().withTranslucent(), simple_translucent_forward }, + { Key::Builder().withUnlit(), simple_unlit_forward }, + { Key::Builder().withTranslucent().withUnlit(), simple_translucent_unlit_forward }, - // Simple Translucents - addPipeline(Key::Builder().withTranslucent(), program::forward_simple_textured_transparent); - addPipeline(Key::Builder().withTranslucent().withUnlit(), program::simple_transparent_textured_unlit); + // Unskinned + { Key::Builder().withMaterial(), model_forward }, + { Key::Builder().withMaterial().withTangents(), model_normalmap_forward }, + { Key::Builder().withMaterial().withTranslucent(), model_translucent_forward }, + { Key::Builder().withMaterial().withTangents().withTranslucent(), model_normalmap_translucent_forward }, + // Unskinned Unlit + { Key::Builder().withMaterial().withUnlit(), model_unlit_forward }, + { Key::Builder().withMaterial().withTangents().withUnlit(), model_normalmap_unlit_forward }, + { Key::Builder().withMaterial().withTranslucent().withUnlit(), model_translucent_unlit_forward }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit(), model_normalmap_translucent_unlit_forward }, + // Unskinned Lightmapped + { Key::Builder().withMaterial().withLightmap(), model_lightmap_forward }, + { Key::Builder().withMaterial().withTangents().withLightmap(), model_normalmap_lightmap_forward }, + { Key::Builder().withMaterial().withTranslucent().withLightmap(), model_translucent_lightmap_forward }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightmap(), model_normalmap_translucent_lightmap_forward }, - // Opaques - addPipeline(Key::Builder().withMaterial(), program::forward_model); - addPipeline(Key::Builder().withMaterial().withLightmap(), program::forward_model_lightmap); - addPipeline(Key::Builder().withMaterial().withUnlit(), program::forward_model_unlit); - addPipeline(Key::Builder().withMaterial().withTangents(), program::forward_model_normal_map); - addPipeline(Key::Builder().withMaterial().withTangents().withLightmap(), program::forward_model_normal_map_lightmap); + // Matrix palette skinned + { Key::Builder().withMaterial().withDeformed(), model_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withDeformed(), model_normalmap_forward_deformed }, + { Key::Builder().withMaterial().withTranslucent().withDeformed(), model_translucent_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withDeformed(), model_normalmap_translucent_forward_deformed }, + // Matrix palette skinned Unlit + { Key::Builder().withMaterial().withUnlit().withDeformed(), model_unlit_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withUnlit().withDeformed(), model_normalmap_unlit_forward_deformed }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withDeformed(), model_translucent_unlit_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withDeformed(), model_normalmap_translucent_unlit_forward_deformed }, + // Matrix palette skinned Lightmapped + { Key::Builder().withMaterial().withLightmap().withDeformed(), model_lightmap_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withLightmap().withDeformed(), model_normalmap_lightmap_forward_deformed }, + { Key::Builder().withMaterial().withTranslucent().withLightmap().withDeformed(), model_translucent_lightmap_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightmap().withDeformed(), model_normalmap_translucent_lightmap_forward_deformed }, - // Deformed Opaques - addPipeline(Key::Builder().withMaterial().withDeformed(), program::forward_deformed_model); - addPipeline(Key::Builder().withMaterial().withDeformed().withTangents(), program::forward_deformed_model_normal_map); - addPipeline(Key::Builder().withMaterial().withDeformed().withDualQuatSkinned(), program::forward_deformed_model_dq); - addPipeline(Key::Builder().withMaterial().withDeformed().withTangents().withDualQuatSkinned(), program::forward_deformed_model_normal_map_dq); + // Dual quaternion skinned + { Key::Builder().withMaterial().withDeformed().withDualQuatSkinned(), model_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withDeformed().withDualQuatSkinned(), model_normalmap_forward_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withDeformed().withDualQuatSkinned(), model_translucent_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_forward_deformeddq }, + // Dual quaternion skinned Unlit + { Key::Builder().withMaterial().withUnlit().withDeformed().withDualQuatSkinned(), model_unlit_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withUnlit().withDeformed().withDualQuatSkinned(), model_normalmap_unlit_forward_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withDeformed().withDualQuatSkinned(), model_translucent_unlit_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_unlit_forward_deformeddq }, + // Dual quaternion skinned Lightmapped + { Key::Builder().withMaterial().withLightmap().withDeformed().withDualQuatSkinned(), model_lightmap_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withLightmap().withDeformed().withDualQuatSkinned(), model_normalmap_lightmap_forward_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withLightmap().withDeformed().withDualQuatSkinned(), model_translucent_lightmap_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightmap().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_lightmap_forward_deformeddq }, + }; - // Translucents - addPipeline(Key::Builder().withMaterial().withTranslucent(), program::forward_model_translucent); - addPipeline(Key::Builder().withMaterial().withTranslucent().withTangents(), program::forward_model_normal_map_translucent); - - // Deformed Translucents - addPipeline(Key::Builder().withMaterial().withDeformed().withTranslucent(), program::forward_deformed_translucent); - addPipeline(Key::Builder().withMaterial().withDeformed().withTranslucent().withTangents(), program::forward_deformed_translucent_normal_map); - addPipeline(Key::Builder().withMaterial().withDeformed().withTranslucent().withDualQuatSkinned(), program::forward_deformed_translucent_dq); - addPipeline(Key::Builder().withMaterial().withDeformed().withTranslucent().withTangents().withDualQuatSkinned(), program::forward_deformed_translucent_normal_map_dq); - - // FIXME: incorrent pipelines for normal mapped + translucent models + for (auto& pipeline : pipelines) { + addPipeline(pipeline.first, pipeline.second); + } forceLightBatchSetter = false; } @@ -300,8 +295,7 @@ void addPlumberPipeline(ShapePlumber& plumber, baseBatchSetter(pipeline, batch, args); extraBatchSetter(pipeline, batch, args); }; - } - else { + } else { finalBatchSetter = baseBatchSetter; } plumber.addPipeline(builder.build(), program, state, finalBatchSetter, itemSetter); @@ -362,17 +356,17 @@ void initZPassPipelines(ShapePlumber& shapePlumber, gpu::StatePointer state, con shapePlumber.addPipeline( ShapeKey::Filter::Builder().withDeformed().withoutDualQuatSkinned().withoutFade(), - gpu::Shader::createProgram(deformed_model_shadow), state); + gpu::Shader::createProgram(model_shadow_deformed), state); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withDeformed().withoutDualQuatSkinned().withFade(), - gpu::Shader::createProgram(deformed_model_shadow_fade), state, extraBatchSetter, itemSetter); + gpu::Shader::createProgram(model_shadow_fade_deformed), state, extraBatchSetter, itemSetter); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withDeformed().withDualQuatSkinned().withoutFade(), - gpu::Shader::createProgram(deformed_model_shadow_dq), state); + gpu::Shader::createProgram(model_shadow_deformeddq), state); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withDeformed().withDualQuatSkinned().withFade(), - gpu::Shader::createProgram(deformed_model_shadow_fade_dq), state, extraBatchSetter, itemSetter); + gpu::Shader::createProgram(model_shadow_fade_deformeddq), state, extraBatchSetter, itemSetter); } bool RenderPipelines::bindMaterial(graphics::MaterialPointer& material, gpu::Batch& batch, render::Args::RenderMode renderMode, bool enableTextures) { diff --git a/libraries/render-utils/src/deferred_light.slv b/libraries/render-utils/src/deferred_light.slv index 164fd9fb3b..31ec378456 100644 --- a/libraries/render-utils/src/deferred_light.slv +++ b/libraries/render-utils/src/deferred_light.slv @@ -26,7 +26,7 @@ void main(void) { ); vec4 pos = UNIT_QUAD[gl_VertexID]; - _texCoord01.xy = (pos.xy + 1.0) * 0.5; + _texCoord01 = vec4((pos.xy + 1.0) * 0.5, 0.0, 0.0); gl_Position = pos; } diff --git a/libraries/render-utils/src/deformed_model.slv b/libraries/render-utils/src/deformed_model.slv deleted file mode 100644 index 8c6d3d049d..0000000000 --- a/libraries/render-utils/src/deformed_model.slv +++ /dev/null @@ -1,56 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include graphics/MaterialTextures.slh@> -<$declareMaterialTexMapArrayBuffer()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(1, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include LightingModel.slh@> - - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - vec3 deformedNormal = vec3(0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, inNormal.xyz, deformedNormal, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // pass along the color - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> - - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> -} diff --git a/libraries/render-utils/src/deformed_model_dq.slv b/libraries/render-utils/src/deformed_model_dq.slv deleted file mode 100644 index 56ac1b6558..0000000000 --- a/libraries/render-utils/src/deformed_model_dq.slv +++ /dev/null @@ -1,53 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include graphics/MaterialTextures.slh@> -<$declareMaterialTexMapArrayBuffer()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(1, _SCRIBE_NULL, 1, 1, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - vec3 deformedNormal = vec3(0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, inNormal.xyz, deformedNormal, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // pass along the color - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> - - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> -} diff --git a/libraries/render-utils/src/deformed_model_normal_map.slv b/libraries/render-utils/src/deformed_model_normal_map.slv deleted file mode 100644 index 85e164b639..0000000000 --- a/libraries/render-utils/src/deformed_model_normal_map.slv +++ /dev/null @@ -1,56 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include graphics/MaterialTextures.slh@> -<$declareMaterialTexMapArrayBuffer()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(1, 1, 1, _SCRIBE_NULL, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) out vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - vec3 deformedNormal = vec3(0.0, 0.0, 0.0); - vec3 deformedTangent = vec3(0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, inNormal.xyz, deformedNormal, inTangent.xyz, deformedTangent, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // pass along the color - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> - <$transformModelToWorldDir(cam, obj, deformedTangent, _tangentWS.xyz)$> - - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> -} diff --git a/libraries/render-utils/src/deformed_model_normal_map_dq.slv b/libraries/render-utils/src/deformed_model_normal_map_dq.slv deleted file mode 100644 index 807d343643..0000000000 --- a/libraries/render-utils/src/deformed_model_normal_map_dq.slv +++ /dev/null @@ -1,57 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<@include render-utils/ShaderConstants.h@> -<$declareStandardTransform()$> - -<@include graphics/MaterialTextures.slh@> -<$declareMaterialTexMapArrayBuffer()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(1, 1, 1, 1, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) out vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - vec3 deformedNormal = vec3(0.0, 0.0, 0.0); - vec3 deformedTangent = vec3(0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, inNormal.xyz, deformedNormal, inTangent.xyz, deformedTangent, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // pass along the color - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> - <$transformModelToWorldDir(cam, obj, deformedTangent, _tangentWS.xyz)$> - - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> -} diff --git a/libraries/render-utils/src/deformed_model_shadow.slv b/libraries/render-utils/src/deformed_model_shadow.slv deleted file mode 100644 index 827fc69b32..0000000000 --- a/libraries/render-utils/src/deformed_model_shadow.slv +++ /dev/null @@ -1,52 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Inputs.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> - -<$declareMaterialTexMapArrayBuffer()$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, deformedPosition, gl_Position)$> - <$transformModelToWorldPos(obj, deformedPosition, _positionWS)$> - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - _texCoord01 = vec4(0.0, 0.0, 0.0, 0.0); - // If we have an opacity mask than we need the first tex coord - if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - } -} - diff --git a/libraries/render-utils/src/deformed_model_shadow_dq.slv b/libraries/render-utils/src/deformed_model_shadow_dq.slv deleted file mode 100644 index 646fc12ce9..0000000000 --- a/libraries/render-utils/src/deformed_model_shadow_dq.slv +++ /dev/null @@ -1,51 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Inputs.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, 1, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> - -<$declareMaterialTexMapArrayBuffer()$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, deformedPosition, gl_Position)$> - <$transformModelToWorldPos(obj, deformedPosition, _positionWS)$> - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - _texCoord01 = vec4(0.0, 0.0, 0.0, 0.0); - // If we have an opacity mask than we need the first tex coord - if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - } -} diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index b1cfc26c66..ecacff38f6 100644 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -15,7 +15,7 @@ <@include DeferredBufferRead.slh@> -<@include DeferredGlobalLight.slh@> +<@include GlobalLight.slh@> <@include render-utils/ShaderConstants.h@> <$declareEvalLightmappedColor()$> diff --git a/libraries/render-utils/src/directional_ambient_light_shadow.slf b/libraries/render-utils/src/directional_ambient_light_shadow.slf index 6b9fb80232..c6763eb372 100644 --- a/libraries/render-utils/src/directional_ambient_light_shadow.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow.slf @@ -14,7 +14,7 @@ <@include Shadow.slh@> <@include DeferredBufferRead.slh@> -<@include DeferredGlobalLight.slh@> +<@include GlobalLight.slh@> <@include render-utils/ShaderConstants.h@> <$declareEvalLightmappedColor()$> diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index b820b3d17f..f6044b2d89 100644 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -13,7 +13,7 @@ // <@include DeferredBufferRead.slh@> -<@include DeferredGlobalLight.slh@> +<@include GlobalLight.slh@> <@include render-utils/ShaderConstants.h@> <$declareEvalLightmappedColor()$> diff --git a/libraries/render-utils/src/directional_skybox_light_shadow.slf b/libraries/render-utils/src/directional_skybox_light_shadow.slf index 8716d60d54..7af0eafd9a 100644 --- a/libraries/render-utils/src/directional_skybox_light_shadow.slf +++ b/libraries/render-utils/src/directional_skybox_light_shadow.slf @@ -14,7 +14,7 @@ <@include Shadow.slh@> <@include DeferredBufferRead.slh@> -<@include DeferredGlobalLight.slh@> +<@include GlobalLight.slh@> <@include render-utils/ShaderConstants.h@> <$declareEvalLightmappedColor()$> diff --git a/libraries/render-utils/src/forward_grid.slf b/libraries/render-utils/src/forward_grid.slf deleted file mode 100644 index e34794bfed..0000000000 --- a/libraries/render-utils/src/forward_grid.slf +++ /dev/null @@ -1,40 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 5/9/19 -// Copyright 2019 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/ShaderConstants.h@> -<@include gpu/Paint.slh@> - -struct Grid { - vec4 period; - vec4 offset; - vec4 edge; -}; - -LAYOUT(binding=0) uniform gridBuffer { - Grid grid; -}; - -layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0; -layout(location=GPU_ATTR_COLOR) in vec4 varColor; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge), - paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy), - float(grid.edge.z == 0.0)); - - if (alpha < 0.0001) { - discard; - } - - _fragColor0 = vec4(varColor.xyz, 1.0); -} diff --git a/libraries/render-utils/src/forward_grid_translucent.slf b/libraries/render-utils/src/forward_grid_translucent.slf deleted file mode 100644 index df0494a22e..0000000000 --- a/libraries/render-utils/src/forward_grid_translucent.slf +++ /dev/null @@ -1,41 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 5/9/19 -// Copyright 2019 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/ShaderConstants.h@> -<@include gpu/Paint.slh@> - -struct Grid { - vec4 period; - vec4 offset; - vec4 edge; -}; - -LAYOUT(binding=0) uniform gridBuffer { - Grid grid; -}; - -layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0; -layout(location=GPU_ATTR_COLOR) in vec4 varColor; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge), - paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy), - float(grid.edge.z == 0.0)); - alpha *= varColor.w; - - if (alpha < 0.0001) { - discard; - } - - _fragColor0 = vec4(varColor.xyz, alpha); -} diff --git a/libraries/render-utils/src/forward_model.slf b/libraries/render-utils/src/forward_model.slf deleted file mode 100644 index daccd9c6d6..0000000000 --- a/libraries/render-utils/src/forward_model.slf +++ /dev/null @@ -1,83 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include ForwardGlobalLight.slh@> - -<$declareEvalSkyboxGlobalColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPosition = _positionES.xyz; - vec3 fragNormal = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - - vec4 color = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - occlusion, - fragPosition, - fragNormal, - albedo, - fresnel, - metallic, - roughness), - opacity); - color.rgb += emissive * isEmissiveEnabled(); - - _fragColor0 = color; -} diff --git a/libraries/render-utils/src/forward_model_lightmap.slf b/libraries/render-utils/src/forward_model_lightmap.slf deleted file mode 100644 index aa1d6dc3b8..0000000000 --- a/libraries/render-utils/src/forward_model_lightmap.slf +++ /dev/null @@ -1,71 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include ForwardGlobalLight.slh@> - -<$declareEvalLightmappedColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> -<$declareMaterialLightmap()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fragNormal = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - - vec4 color = vec4(evalLightmappedColor( - cam._viewInverse, - 1.0, - 1.0, - fragNormal, - albedo, - lightmap), - opacity); - - _fragColor0 = color; -} diff --git a/libraries/render-utils/src/forward_model_normal_map.slf b/libraries/render-utils/src/forward_model_normal_map.slf deleted file mode 100644 index 33e375c495..0000000000 --- a/libraries/render-utils/src/forward_model_normal_map.slf +++ /dev/null @@ -1,85 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include ForwardGlobalLight.slh@> - -<$declareEvalSkyboxGlobalColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPosition = _positionES.xyz; - vec3 fragNormal; - <$evalMaterialNormalLOD(fragPosition, normalTex, _normalWS, _tangentWS, fragNormal)$> - - TransformCamera cam = getTransformCamera(); - - vec4 color = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - occlusion, - fragPosition, - fragNormal, - albedo, - fresnel, - metallic, - roughness), - opacity); - color.rgb += emissive * isEmissiveEnabled(); - - _fragColor0 = color; -} diff --git a/libraries/render-utils/src/forward_model_normal_map_lightmap.slf b/libraries/render-utils/src/forward_model_normal_map_lightmap.slf deleted file mode 100644 index c36f3d51c6..0000000000 --- a/libraries/render-utils/src/forward_model_normal_map_lightmap.slf +++ /dev/null @@ -1,74 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include ForwardGlobalLight.slh@> - -<$declareEvalLightmappedColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> -<$declareMaterialLightmap()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fragPosition = _positionES.xyz; - vec3 fragNormal; - <$evalMaterialNormalLOD(fragPosition, normalTex, _normalWS, _tangentWS, fragNormal)$> - - TransformCamera cam = getTransformCamera(); - - vec4 color = vec4(evalLightmappedColor( - cam._viewInverse, - 1.0, - 1.0, - fragNormal, - albedo, - lightmap), - opacity); - - _fragColor0 = color; -} diff --git a/libraries/render-utils/src/forward_model_translucent.slf b/libraries/render-utils/src/forward_model_translucent.slf deleted file mode 100644 index 080ed7eea3..0000000000 --- a/libraries/render-utils/src/forward_model_translucent.slf +++ /dev/null @@ -1,81 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include ForwardGlobalLight.slh@> - -<$declareEvalGlobalLightingAlphaBlended()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - vec3 fragPosition = _positionES.xyz; - vec3 fragNormal = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - occlusion, - fragPosition, - fragNormal, - albedo, - fresnel, - metallic, - emissive, - roughness, opacity), - opacity); -} diff --git a/libraries/render-utils/src/forward_model_unlit.slf b/libraries/render-utils/src/forward_model_unlit.slf deleted file mode 100644 index ccd264f0bf..0000000000 --- a/libraries/render-utils/src/forward_model_unlit.slf +++ /dev/null @@ -1,42 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 5/5/2016. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightingModel.slh@> - -<$declareMaterialTextures(ALBEDO)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - _fragColor0 = vec4(albedo * isUnlitEnabled(), 1.0); -} diff --git a/libraries/render-utils/src/forward_parabola.slf b/libraries/render-utils/src/forward_parabola.slf deleted file mode 100644 index b0def6db6b..0000000000 --- a/libraries/render-utils/src/forward_parabola.slf +++ /dev/null @@ -1,18 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 5/9/19 -// Copyright 2019 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -layout(location=0) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - _fragColor0 = _color; -} diff --git a/libraries/render-utils/src/forward_sdf_text3D.slf b/libraries/render-utils/src/forward_sdf_text3D.slf deleted file mode 100644 index 09b10c0c42..0000000000 --- a/libraries/render-utils/src/forward_sdf_text3D.slf +++ /dev/null @@ -1,57 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// sdf_text3D_transparent.frag -// fragment shader -// -// Created by Bradley Austin Davis on 2015-02-04 -// Based on fragment shader code from -// https://github.com/paulhoux/Cinder-Samples/blob/master/TextRendering/include/text/Text.cpp -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -<@include DefaultMaterials.slh@> - -<@include ForwardGlobalLight.slh@> -<$declareEvalSkyboxGlobalColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include render-utils/ShaderConstants.h@> - -<@include sdf_text3D.slh@> -<$declareEvalSDFSuperSampled()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -layout(location=0) out vec4 _fragColor0; - -void main() { - float a = evalSDFSuperSampled(_texCoord0); - - float alpha = a * _color.a; - if (alpha <= 0.0) { - discard; - } - - TransformCamera cam = getTransformCamera(); - vec3 fragPosition = _positionES.xyz; - - _fragColor0 = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS), - _color.rgb, - DEFAULT_FRESNEL, - DEFAULT_METALLIC, - DEFAULT_ROUGHNESS), - 1.0); -} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple.slf b/libraries/render-utils/src/forward_simple.slf deleted file mode 100644 index 677c369033..0000000000 --- a/libraries/render-utils/src/forward_simple.slf +++ /dev/null @@ -1,61 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// forward_simple.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/15/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -<@include DefaultMaterials.slh@> - -<@include ForwardGlobalLight.slh@> -<$declareEvalSkyboxGlobalColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normalMS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _positionMS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; - -// For retro-compatibility -#define _normal _normalWS -#define _modelNormal _normalMS -#define _position _positionMS -#define _eyePosition _positionES - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - vec3 normal = normalize(_normalWS.xyz); - vec3 diffuse = _color.rgb; - vec3 specular = DEFAULT_SPECULAR; - float shininess = DEFAULT_SHININESS; - float emissiveAmount = 0.0; - - TransformCamera cam = getTransformCamera(); - vec3 fragPosition = _positionES.xyz; - - _fragColor0 = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normal, - diffuse, - DEFAULT_FRESNEL, - length(specular), - max(0.0, 1.0 - shininess / 128.0)), - 1.0); -} diff --git a/libraries/render-utils/src/forward_simple_textured.slf b/libraries/render-utils/src/forward_simple_textured.slf deleted file mode 100644 index 373ab13d1a..0000000000 --- a/libraries/render-utils/src/forward_simple_textured.slf +++ /dev/null @@ -1,58 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// forward_simple_textured.frag -// fragment shader -// -// Created by Clément Brisset on 5/29/15. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -<@include gpu/Color.slh@> -<@include DefaultMaterials.slh@> - -<@include ForwardGlobalLight.slh@> -<$declareEvalSkyboxGlobalColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include render-utils/ShaderConstants.h@> - -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - vec3 albedo = _color.xyz * texel.xyz; - float metallic = DEFAULT_METALLIC; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - TransformCamera cam = getTransformCamera(); - vec3 fragPosition = _positionES.xyz; - - _fragColor0 = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS), - albedo, - fresnel, - metallic, - DEFAULT_ROUGHNESS), - 1.0); -} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple_textured_transparent.slf b/libraries/render-utils/src/forward_simple_textured_transparent.slf deleted file mode 100644 index 1b5047507b..0000000000 --- a/libraries/render-utils/src/forward_simple_textured_transparent.slf +++ /dev/null @@ -1,60 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// forward_simple_textured_transparent.frag -// fragment shader -// -// Created by Clément Brisset on 5/29/15. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -<@include gpu/Color.slh@> -<@include DefaultMaterials.slh@> - -<@include ForwardGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include render-utils/ShaderConstants.h@> - -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - vec3 albedo = _color.xyz * texel.xyz; - float alpha = _color.a * texel.a; - float metallic = DEFAULT_METALLIC; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - TransformCamera cam = getTransformCamera(); - vec3 fragPosition = _positionES.xyz; - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS), - albedo, - fresnel, - metallic, - DEFAULT_EMISSIVE, - DEFAULT_ROUGHNESS, alpha), - alpha); -} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple_textured_unlit.slf b/libraries/render-utils/src/forward_simple_textured_unlit.slf deleted file mode 100644 index ddbc5ae4d7..0000000000 --- a/libraries/render-utils/src/forward_simple_textured_unlit.slf +++ /dev/null @@ -1,35 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// forward_simple_textured_unlit.frag -// fragment shader -// -// Created by Clément Brisset on 5/29/15. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include LightingModel.slh@> -<@include gpu/Color.slh@> - -<@include render-utils/ShaderConstants.h@> - -layout(location=0) out vec4 _fragColor0; - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0.st); - float colorAlpha = _color.a * texel.a; - - _fragColor0 = vec4(_color.rgb * texel.rgb * isUnlitEnabled(), colorAlpha); -} \ No newline at end of file diff --git a/libraries/render-utils/src/glowLine.slf b/libraries/render-utils/src/glowLine.slf deleted file mode 100644 index c65d8d6488..0000000000 --- a/libraries/render-utils/src/glowLine.slf +++ /dev/null @@ -1,34 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Bradley Austin Davis on 2016/07/05 -// Copyright 2013-2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=0) in float distanceFromCenter; -layout(location=0) out vec4 _fragColor; - -void main(void) { - // The incoming value actually ranges from -1 to 1, so modify it - // so that it goes from 0 -> 1 -> 0 with the solid alpha being at - // the center of the line - float alpha = 1.0 - abs(distanceFromCenter); - - // Convert from a linear alpha curve to a sharp peaked one - alpha = _color.a * pow(alpha, 10.0); - - // Drop everything where the curve falls off to nearly nothing - if (alpha <= 0.05) { - discard; - } - - // Emit the color - _fragColor = vec4(_color.rgb, alpha); -} diff --git a/libraries/render-utils/src/glowLine.slv b/libraries/render-utils/src/glowLine.slv deleted file mode 100644 index 1bcb25817c..0000000000 --- a/libraries/render-utils/src/glowLine.slv +++ /dev/null @@ -1,61 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Bradley Austin Davis on 2016/07/05 -// Copyright 2013-2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Transform.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareStandardTransform()$> - -struct LineData { - vec4 p1; - vec4 p2; - vec4 color; - float width; -}; - -LAYOUT_STD140(binding=0) uniform LineDataBuffer { - LineData _lineData; -}; - -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; -// the distance from the center in 'quad space' -layout(location=0) out float distanceFromCenter; - -void main(void) { - _color = _lineData.color; - - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - - vec4 p1eye, p2eye; - <$transformModelToEyePos(cam, obj, _lineData.p1, p1eye)$> - <$transformModelToEyePos(cam, obj, _lineData.p2, p2eye)$> - p1eye /= p1eye.w; - p2eye /= p2eye.w; - - // Find the line direction - vec3 v1 = normalize(p1eye.xyz - p2eye.xyz); - // Find the vector from the eye to one of the points - vec3 v2 = normalize(p1eye.xyz); - // The orthogonal vector is the cross product of these two - vec3 orthogonal = cross(v1, v2) * _lineData.width; - - // Deteremine which end to emit based on the vertex id (even / odd) - vec4 eye = mix(p2eye, p1eye, float(gl_VertexID % 2 == 0)); - - // Add or subtract the orthogonal vector based on a different vertex ID - // calculation - distanceFromCenter = 1.0 - 2.0 * float(gl_VertexID < 2); - eye.xyz += distanceFromCenter * orthogonal; - - // Finally, put the eyespace vertex into clip space - <$transformEyeToClipPos(cam, eye, gl_Position)$> -} diff --git a/libraries/render-utils/src/grid.slf b/libraries/render-utils/src/grid.slf index 50c420bc10..68e6d019c0 100644 --- a/libraries/render-utils/src/grid.slf +++ b/libraries/render-utils/src/grid.slf @@ -1,5 +1,6 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // // Created by Zach Pomerantz on 2/16/2016. @@ -9,11 +10,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBufferWrite.slh@> - <@include gpu/ShaderConstants.h@> <@include gpu/Paint.slh@> +<@if not HIFI_USE_FORWARD@> + <@include DeferredBufferWrite.slh@> +<@else@> + layout(location=0) out vec4 _fragColor0; +<@endif@> + struct Grid { vec4 period; vec4 offset; @@ -32,9 +37,17 @@ void main(void) { paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy), float(grid.edge.z == 0.0)); - if (alpha < 0.0001) { +<@if not HIFI_USE_FORWARD@> + <@if not HIFI_USE_TRANSLUCENT@> + packDeferredFragmentUnlit(vec3(1.0, 0.0, 0.0), alpha, varColor.rgb); + <@else@> + packDeferredFragmentTranslucent(vec3(1.0, 0.0, 0.0), alpha, varColor.rgb, DEFAULT_ROUGHNESS); + <@endif@> +<@else@> + const float EPSILON = 0.0001; + if (alpha < EPSILON) { discard; } - - packDeferredFragmentUnlit(vec3(1.0, 0.0, 0.0), 1.0, varColor.xyz); + _fragColor0 = vec4(varColor.rgb, alpha); +<@endif@> } diff --git a/libraries/render-utils/src/grid_translucent.slf b/libraries/render-utils/src/grid_translucent.slf deleted file mode 100644 index bb61126991..0000000000 --- a/libraries/render-utils/src/grid_translucent.slf +++ /dev/null @@ -1,41 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 12/22/18 -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> - -<@include gpu/ShaderConstants.h@> -<@include gpu/Paint.slh@> - -struct Grid { - vec4 period; - vec4 offset; - vec4 edge; -}; - -LAYOUT(binding=0) uniform gridBuffer { - Grid grid; -}; - -layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0; -layout(location=GPU_ATTR_COLOR) in vec4 varColor; - -void main(void) { - float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge), - paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy), - float(grid.edge.z == 0.0)); - alpha *= varColor.w; - - if (alpha < 0.0001) { - discard; - } - - packDeferredFragmentTranslucent(vec3(1.0, 0.0, 0.0), alpha, varColor.xyz, DEFAULT_ROUGHNESS); -} diff --git a/libraries/render-utils/src/hmd_ui.slv b/libraries/render-utils/src/hmd_ui.slv index 6e782d1672..75423d1882 100644 --- a/libraries/render-utils/src/hmd_ui.slv +++ b/libraries/render-utils/src/hmd_ui.slv @@ -29,7 +29,7 @@ LAYOUT_STD140(binding=0) uniform hudBuffer { layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; void main() { - _texCoord01.xy = inTexCoord0.st; + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); // standard transform TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index edf5064324..7803974ec8 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -1,6 +1,6 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // // Created by Andrzej Kapolka on 5/6/14. @@ -10,55 +10,313 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBufferWrite.slh@> <@include graphics/Material.slh@> <@include graphics/MaterialTextures.slh@> <@include render-utils/ShaderConstants.h@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> +<@if not HIFI_USE_SHADOW@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + <@include DefaultMaterials.slh@> + <@include GlobalLight.slh@> + <@if HIFI_USE_LIGHTMAP@> + <$declareEvalLightmappedColor()$> + <@elif HIFI_USE_TRANSLUCENT@> + <@if not HIFI_USE_FORWARD@> + <@include LightLocal.slh@> + <$declareEvalGlobalLightingAlphaBlendedWithHaze()$> + <@else@> + <$declareEvalGlobalLightingAlphaBlended()$> + <@endif@> + <@else@> + <$declareEvalSkyboxGlobalColor()$> + <@endif@> + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + layout(location=0) out vec4 _fragColor0; + <@else@> + <@include DeferredBufferWrite.slh@> + <@endif@> +<@else@> + layout(location=0) out vec4 _fragColor0; +<@endif@> +<@if HIFI_USE_UNLIT@> + <@include LightingModel.slh@> +<@endif@> + +<@if HIFI_USE_SHADOW or HIFI_USE_UNLIT@> + <$declareMaterialTextures(ALBEDO)$> +<@else@> + <@if not HIFI_USE_LIGHTMAP@> + <@if HIFI_USE_NORMALMAP and HIFI_USE_TRANSLUCENT@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL , METALLIC, EMISSIVE, OCCLUSION)$> + <@elif HIFI_USE_NORMALMAP@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL , METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> + <@elif HIFI_USE_TRANSLUCENT@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL , METALLIC, EMISSIVE, OCCLUSION)$> + <@else@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL , METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> + <@endif@> + <@else@> + <@if HIFI_USE_NORMALMAP@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> + <@else@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> + <@endif@> + <$declareMaterialLightmap()$> + <@endif@> +<@endif@> + +<@if HIFI_USE_FADE@> + <@include Fade.slh@> + <$declareFadeFragment()$> +<@endif@> + +layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy #define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; +<@if not HIFI_USE_SHADOW@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; + layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; + <@if HIFI_USE_NORMALMAP@> + layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; + <@endif@> +<@endif@> void main(void) { +<@if HIFI_USE_FADE@> + <@if not HIFI_USE_SHADOW@> + vec3 fadeEmissive; + FadeObjectParams fadeParams; + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _positionWS.xyz, fadeEmissive); + <@else@> + FadeObjectParams fadeParams; + <$fetchFadeObjectParams(fadeParams)$> + applyFadeClip(fadeParams, _positionWS.xyz); + <@endif@> +<@endif@> + Material mat = getMaterial(); BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, scatteringTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> +<@if HIFI_USE_SHADOW or HIFI_USE_UNLIT@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <@if HIFI_USE_TRANSLUCENT@> + <$discardInvisible(opacity)$>; + <@else@> + <$discardTransparent(opacity)$>; + <@endif@> - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; + <@if not HIFI_USE_SHADOW@> + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color.rgb; + <@if HIFI_USE_FADE@> + albedo += fadeEmissive; + <@endif@> + <@endif@> - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + <@if HIFI_USE_SHADOW@> + _fragColor0 = vec4(1.0); + <@elif HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + _fragColor0 = vec4(albedo * isUnlitEnabled(), opacity); + <@else@> + packDeferredFragmentUnlit( + normalize(_normalWS), + opacity, + albedo * isUnlitEnabled()); + <@endif@> +<@else@> + <@if not HIFI_USE_LIGHTMAP@> + <@if HIFI_USE_NORMALMAP and HIFI_USE_TRANSLUCENT@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, _SCRIBE_NULL)$> + <@elif HIFI_USE_NORMALMAP@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, scatteringTex)$> + <@elif HIFI_USE_TRANSLUCENT@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, _SCRIBE_NULL)$> + <@else@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, scatteringTex)$> + <@endif@> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + <@else@> + <@if HIFI_USE_NORMALMAP@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex)$> + <@else@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex)$> + <@endif@> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> + <@endif@> - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <@if HIFI_USE_TRANSLUCENT@> + <$discardInvisible(opacity)$>; + <@else@> + <$discardTransparent(opacity)$>; + <@endif@> - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color.rgb; - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - float scattering = getMaterialScattering(mat); - <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - packDeferredFragment( - normalize(_normalWS), - opacity, - albedo, - roughness, - metallic, - emissive, - occlusion, - scattering); + <@if not HIFI_USE_LIGHTMAP@> + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + float occlusion = DEFAULT_OCCLUSION; + <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; + + <@if not HIFI_USE_TRANSLUCENT@> + float scattering = getMaterialScattering(mat); + <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; + <@endif@> + <@endif@> + + <@if HIFI_USE_NORMALMAP@> + vec3 fragNormalWS; + <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$> + <@else@> + vec3 fragNormalWS = _normalWS; + <@endif@> + + <@if HIFI_USE_FORWARD@> + TransformCamera cam = getTransformCamera(); + vec3 fresnel = getFresnelF0(metallic, albedo); + <@if not HIFI_USE_TRANSLUCENT@> + <@if not HIFI_USE_LIGHTMAP@> + vec4 color = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + occlusion, + _positionES.xyz, + fragNormalWS, + albedo, + fresnel, + metallic, + roughness), + opacity); + color.rgb += emissive * isEmissiveEnabled(); + _fragColor0 = color; + <@else@> + _fragColor0 = vec4(evalLightmappedColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragNormalWS, + albedo, + lightmap), + opacity); + <@endif@> + <@else@> + <@if not HIFI_USE_LIGHTMAP@> + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + occlusion, + _positionES.xyz, + fragNormalWS, + albedo, + fresnel, + metallic, + emissive, + roughness, opacity), + opacity); + <@else@> + _fragColor0 = vec4(evalLightmappedColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragNormalWS, + albedo, + lightmap), + opacity); + <@endif@> + <@endif@> + <@else@> + <@if not HIFI_USE_TRANSLUCENT@> + <@if not HIFI_USE_LIGHTMAP@> + packDeferredFragment( + normalize(fragNormalWS), + opacity, + albedo, + roughness, + metallic, + emissive + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , + occlusion, + scattering); + <@else@> + packDeferredFragmentLightmap( + normalize(fragNormalWS), + evalOpaqueFinalAlpha(getMaterialOpacity(mat), opacity), + albedo, + roughness, + metallic, + lightmap + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + ); + <@endif@> + <@else@> + TransformCamera cam = getTransformCamera(); + <@if not HIFI_USE_LIGHTMAP@> + vec3 fresnel = getFresnelF0(metallic, albedo); + + vec3 fragPositionWS = _positionWS.xyz; + vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS; + vec3 fragToEyeDirWS = normalize(fragToEyeWS); + SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS); + + vec4 localLighting = vec4(0.0); + <$fetchClusterInfo(_positionWS)$>; + if (hasLocalLights(numLights, clusterPos, dims)) { + localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS, + metallic, fresnel, albedo, 0.0, + vec4(0), vec4(0), opacity); + } + + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + occlusion, + _positionES.xyz, + fragPositionWS, + albedo, + fresnel, + metallic, + emissive + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , + surfaceWS, opacity, localLighting.rgb), + opacity); + <@else@> + _fragColor0 = vec4(evalLightmappedColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragNormalWS, + albedo, + lightmap), + opacity); + <@endif@> + <@endif@> + <@endif@> +<@endif@> } diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 88cbd1e18c..319711eac2 100644 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -1,10 +1,10 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> +// <$_SCRIBE_FILENAME$> +// Generated on <$_SCRIBE_DATE$> // -// Created by Hifi Engine Team. -// Copyright 2013 High Fidelity, Inc. +// Created by Hifi Engine Team +// Copyright 2019 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -12,32 +12,94 @@ <@include gpu/Inputs.slh@> <@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<@include graphics/MaterialTextures.slh@> - -<$declareStandardTransform()$> - -<$declareMaterialTexMapArrayBuffer()$> - <@include render-utils/ShaderConstants.h@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include graphics/MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@> + <@include MeshDeformer.slh@> + <@if HIFI_USE_DEFORMED@> + <@if HIFI_USE_SHADOW@> + <$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> + <@elif not HIFI_USE_NORMALMAP@> + <$declareMeshDeformer(1, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> + <@else@> + <$declareMeshDeformer(1, 1, 1, _SCRIBE_NULL, 1)$> + <@endif@> + <@else@> + <@if HIFI_USE_SHADOW@> + <$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, 1, 1)$> + <@elif not HIFI_USE_NORMALMAP@> + <$declareMeshDeformer(1, _SCRIBE_NULL, 1, 1, 1)$> + <@else@> + <$declareMeshDeformer(1, 1, 1, 1, 1)$> + <@endif@> + <@endif@> + <$declareMeshDeformerActivation(1, 1)$> +<@endif@> + layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; +<@if not HIFI_USE_SHADOW@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; + layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; + <@if HIFI_USE_NORMALMAP@> + layout(location=RENDER_UTILS_ATTR_TANGENT_WS) out vec3 _tangentWS; + <@endif@> +<@endif@> void main(void) { - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; + vec4 positionMS = inPosition; + vec3 normalMS = inNormal.xyz; + vec3 tangentMS = inTangent.xyz; + +<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@> + evalMeshDeformer(inPosition, positionMS, + <@if not HIFI_USE_SHADOW@> + inNormal.xyz, normalMS, + <@if HIFI_USE_NORMALMAP@> + inTangent.xyz, tangentMS, + <@endif@> + <@endif@> + meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, + meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); +<@endif@> - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, inPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> +<@if not HIFI_USE_SHADOW@> + <$transformModelToWorldAndEyeAndClipPos(cam, obj, positionMS, _positionWS, _positionES, gl_Position)$> + <$transformModelToWorldDir(cam, obj, normalMS, _normalWS)$> +<@else@> + <$transformModelToClipPos(cam, obj, positionMS, gl_Position)$> + <$transformModelToWorldPos(obj, positionMS, _positionWS)$> +<@endif@> - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> +<@if HIFI_USE_NORMALMAP@> + <$transformModelToWorldDir(cam, obj, tangentMS, _tangentWS)$> +<@endif@> + +<@if HIFI_USE_SHADOW@> + Material mat = getMaterial(); + BITFIELD matKey = getMaterialKey(mat); + // If we have an opacity mask than we need the first tex coord + if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + _texCoord01.zw = vec2(0.0); + } else { + _texCoord01 = vec4(0.0); + } +<@else@> + _color = color_sRGBAToLinear(inColor); + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> +<@endif@> } diff --git a/libraries/render-utils/src/model_fade.slf b/libraries/render-utils/src/model_fade.slf deleted file mode 100644 index e931ec4cf0..0000000000 --- a/libraries/render-utils/src/model_fade.slf +++ /dev/null @@ -1,73 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, scatteringTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - float scattering = getMaterialScattering(mat); - <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; - - packDeferredFragment( - normalize(_normalWS), - opacity, - albedo, - roughness, - metallic, - emissive + fadeEmissive, - occlusion, - scattering); -} diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf deleted file mode 100644 index 1be247e3e9..0000000000 --- a/libraries/render-utils/src/model_lightmap.slf +++ /dev/null @@ -1,50 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Samuel Gateau on 11/19/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> -<$declareMaterialLightmap()$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - packDeferredFragmentLightmap( - normalize(_normalWS), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), - albedo, - roughness, - metallic, - lightmap); -} diff --git a/libraries/render-utils/src/model_lightmap_fade.slf b/libraries/render-utils/src/model_lightmap_fade.slf deleted file mode 100644 index 61568463a7..0000000000 --- a/libraries/render-utils/src/model_lightmap_fade.slf +++ /dev/null @@ -1,59 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> -<$declareMaterialLightmap()$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - packDeferredFragmentLightmap( - normalize(_normalWS), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), - albedo, - roughness, - metallic, - lightmap + fadeEmissive); -} diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf deleted file mode 100644 index 3d961584c2..0000000000 --- a/libraries/render-utils/src/model_lightmap_normal_map.slf +++ /dev/null @@ -1,55 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Samuel Gateau on 11/19/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> -<$declareMaterialLightmap()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fragNormal; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormal)$> - - packDeferredFragmentLightmap( - normalize(fragNormal), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), - albedo, - roughness, - metallic, - lightmap); -} diff --git a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf deleted file mode 100644 index f873847474..0000000000 --- a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf +++ /dev/null @@ -1,64 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> -<$declareMaterialLightmap()$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fragNormal; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormal)$> - - packDeferredFragmentLightmap( - normalize(fragNormal), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), - albedo, - roughness, - metallic, - lightmap + fadeEmissive); -} diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf deleted file mode 100644 index 695fadbca8..0000000000 --- a/libraries/render-utils/src/model_normal_map.slf +++ /dev/null @@ -1,69 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Andrzej Kapolka on 5/6/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, scatteringTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - float scattering = getMaterialScattering(mat); - <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; - - vec3 fragNormalWS; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$> - - packDeferredFragment( - normalize(fragNormalWS), - opacity, - albedo, - roughness, - metallic, - emissive, - occlusion, - scattering); -} diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv deleted file mode 100644 index 0fd9a8b582..0000000000 --- a/libraries/render-utils/src/model_normal_map.slv +++ /dev/null @@ -1,45 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareStandardTransform()$> - -<$declareMaterialTexMapArrayBuffer()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) out vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; - -void main(void) { - // pass along the color - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, inPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> - <$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangentWS)$> - - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> -} diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf deleted file mode 100644 index 07b6f47b55..0000000000 --- a/libraries/render-utils/src/model_normal_map_fade.slf +++ /dev/null @@ -1,78 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, scatteringTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - float scattering = getMaterialScattering(mat); - <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; - - vec3 fragNormalWS; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$> - - packDeferredFragment( - normalize(fragNormalWS), - opacity, - albedo, - roughness, - metallic, - emissive + fadeEmissive, - occlusion, - scattering); -} diff --git a/libraries/render-utils/src/model_shadow.slf b/libraries/render-utils/src/model_shadow.slf deleted file mode 100644 index 6d8dfb7e2a..0000000000 --- a/libraries/render-utils/src/model_shadow.slf +++ /dev/null @@ -1,34 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Andrzej Kapolka on 3/24/14. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy - -layout(location=0) out vec4 _fragColor; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - // pass-through to set z-buffer - _fragColor = vec4(1.0, 1.0, 1.0, 0.0); -} diff --git a/libraries/render-utils/src/model_shadow.slv b/libraries/render-utils/src/model_shadow.slv deleted file mode 100644 index d455ea4ade..0000000000 --- a/libraries/render-utils/src/model_shadow.slv +++ /dev/null @@ -1,42 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Inputs.slh@> - -<@include gpu/Transform.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> - -<$declareStandardTransform()$> -<$declareMaterialTexMapArrayBuffer()$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; - -void main(void) { - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> - <$transformModelToWorldPos(obj, inPosition, _positionWS)$> - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - _texCoord01 = vec4(0.0, 0.0, 0.0, 0.0); - // If we have an opacity mask than we need the first tex coord - if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - } -} diff --git a/libraries/render-utils/src/model_shadow_fade.slf b/libraries/render-utils/src/model_shadow_fade.slf deleted file mode 100644 index 1f94d4a0ac..0000000000 --- a/libraries/render-utils/src/model_shadow_fade.slf +++ /dev/null @@ -1,42 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy - -layout(location=0) out vec4 _fragColor; - -void main(void) { - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFadeClip(fadeParams, _positionWS.xyz); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - // pass-through to set z-buffer - _fragColor = vec4(1.0, 1.0, 1.0, 0.0); -} diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf deleted file mode 100644 index 72f6b4c187..0000000000 --- a/libraries/render-utils/src/model_translucent.slf +++ /dev/null @@ -1,96 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightLocal.slh@> -<@include DeferredGlobalLight.slh@> - -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPositionES = _positionES.xyz; - vec3 fragPositionWS = _positionWS.xyz; - // Lighting is done in world space - vec3 fragNormalWS = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS; - vec3 fragToEyeDirWS = normalize(fragToEyeWS); - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS); - - vec4 localLighting = vec4(0.0); - <$fetchClusterInfo(_positionWS)$>; - if (hasLocalLights(numLights, clusterPos, dims)) { - localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS, - metallic, fresnel, albedo, 0.0, - vec4(0), vec4(0), opacity); - } - - _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - occlusion, - fragPositionES, - fragPositionWS, - albedo, - fresnel, - metallic, - emissive, - surfaceWS, opacity, localLighting.rgb), - opacity); -} diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf deleted file mode 100644 index 7e170759c4..0000000000 --- a/libraries/render-utils/src/model_translucent_fade.slf +++ /dev/null @@ -1,104 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightLocal.slh@> -<@include DeferredGlobalLight.slh@> - -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPositionES = _positionES.xyz; - vec3 fragPositionWS = _positionWS.xyz; - // Lighting is done in world space - vec3 fragNormalWS = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS; - vec3 fragToEyeDirWS = normalize(fragToEyeWS); - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS); - - vec4 localLighting = vec4(0.0); - <$fetchClusterInfo(_positionWS)$>; - if (hasLocalLights(numLights, clusterPos, dims)) { - localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS, - metallic, fresnel, albedo, 0.0, - vec4(0), vec4(0), opacity); - } - - _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - occlusion, - fragPositionES, - fragPositionWS, - albedo, - fresnel, - metallic, - emissive + fadeEmissive, - surfaceWS, opacity, localLighting.rgb), - opacity); -} diff --git a/libraries/render-utils/src/model_translucent_normal_map.slf b/libraries/render-utils/src/model_translucent_normal_map.slf deleted file mode 100644 index b3a9127acf..0000000000 --- a/libraries/render-utils/src/model_translucent_normal_map.slf +++ /dev/null @@ -1,98 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 23/01/2018. -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightLocal.slh@> -<@include DeferredGlobalLight.slh@> - -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPositionES = _positionES.xyz; - vec3 fragPositionWS = _positionWS.xyz; - // Lighting is done in world space - vec3 fragNormalWS; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$> - - TransformCamera cam = getTransformCamera(); - vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS; - vec3 fragToEyeDirWS = normalize(fragToEyeWS); - SurfaceData surfaceWS = initSurfaceData(roughness, normalize(fragNormalWS), fragToEyeDirWS); - - vec4 localLighting = vec4(0.0); - <$fetchClusterInfo(_positionWS)$>; - if (hasLocalLights(numLights, clusterPos, dims)) { - localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS, - metallic, fresnel, albedo, 0.0, - vec4(0), vec4(0), opacity); - } - - _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - occlusion, - fragPositionES, - fragPositionWS, - albedo, - fresnel, - metallic, - emissive, - surfaceWS, opacity, localLighting.rgb), - opacity); -} diff --git a/libraries/render-utils/src/model_translucent_normal_map_fade.slf b/libraries/render-utils/src/model_translucent_normal_map_fade.slf deleted file mode 100644 index 4c56ebda2e..0000000000 --- a/libraries/render-utils/src/model_translucent_normal_map_fade.slf +++ /dev/null @@ -1,106 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 23/01/18. -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightLocal.slh@> -<@include DeferredGlobalLight.slh@> - -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPositionES = _positionES.xyz; - vec3 fragPositionWS = _positionWS.xyz; - // Lighting is done in world space - vec3 fragNormalWS; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$> - - TransformCamera cam = getTransformCamera(); - vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS; - vec3 fragToEyeDirWS = normalize(fragToEyeWS); - SurfaceData surfaceWS = initSurfaceData(roughness, normalize(fragNormalWS), fragToEyeDirWS); - - vec4 localLighting = vec4(0.0); - <$fetchClusterInfo(_positionWS)$>; - if (hasLocalLights(numLights, clusterPos, dims)) { - localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS, - metallic, fresnel, albedo, 0.0, - vec4(0), vec4(0), opacity); - } - - _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - occlusion, - fragPositionES, - fragPositionWS, - albedo, - fresnel, - metallic, - emissive + fadeEmissive, - surfaceWS, opacity, localLighting.rgb), - opacity); -} diff --git a/libraries/render-utils/src/model_translucent_unlit.slf b/libraries/render-utils/src/model_translucent_unlit.slf deleted file mode 100644 index 37f58d3da9..0000000000 --- a/libraries/render-utils/src/model_translucent_unlit.slf +++ /dev/null @@ -1,42 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Zach Pomerantz on 2/3/2016. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightingModel.slh@> - -<$declareMaterialTextures(ALBEDO)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - _fragColor = vec4(albedo * isUnlitEnabled(), opacity); -} diff --git a/libraries/render-utils/src/model_translucent_unlit_fade.slf b/libraries/render-utils/src/model_translucent_unlit_fade.slf deleted file mode 100644 index 04d57b7c47..0000000000 --- a/libraries/render-utils/src/model_translucent_unlit_fade.slf +++ /dev/null @@ -1,52 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightingModel.slh@> - -<$declareMaterialTextures(ALBEDO)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - albedo += fadeEmissive; - - _fragColor = vec4(albedo * isUnlitEnabled(), opacity); -} diff --git a/libraries/render-utils/src/model_unlit.slf b/libraries/render-utils/src/model_unlit.slf deleted file mode 100644 index cbac67a72e..0000000000 --- a/libraries/render-utils/src/model_unlit.slf +++ /dev/null @@ -1,45 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 5/5/2016. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include DeferredBufferWrite.slh@> -<@include LightingModel.slh@> - -<$declareMaterialTextures(ALBEDO)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - packDeferredFragmentUnlit( - normalize(_normalWS), - opacity, - albedo * isUnlitEnabled()); -} diff --git a/libraries/render-utils/src/model_unlit_fade.slf b/libraries/render-utils/src/model_unlit_fade.slf deleted file mode 100644 index 3097c04c26..0000000000 --- a/libraries/render-utils/src/model_unlit_fade.slf +++ /dev/null @@ -1,55 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include DeferredBufferWrite.slh@> -<@include LightingModel.slh@> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -<$declareMaterialTextures(ALBEDO)$> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - albedo += fadeEmissive; - - packDeferredFragmentUnlit( - normalize(_normalWS), - opacity, - albedo * isUnlitEnabled()); -} diff --git a/libraries/render-utils/src/parabola.slf b/libraries/render-utils/src/parabola.slf index ea51d7e3af..f19f82ec59 100644 --- a/libraries/render-utils/src/parabola.slf +++ b/libraries/render-utils/src/parabola.slf @@ -1,5 +1,6 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // // Created by Sam Gondelman on 7/18/2018 @@ -9,10 +10,22 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBufferWrite.slh@> +<@if not HIFI_USE_FORWARD@> + <@include DeferredBufferWrite.slh@> +<@else@> + layout(location=0) out vec4 _fragColor0; +<@endif@> layout(location=0) in vec4 _color; void main(void) { - packDeferredFragmentUnlit(vec3(1.0, 0.0, 0.0), 1.0, _color.rgb); +<@if not HIFI_USE_FORWARD@> + <@if not HIFI_USE_TRANSLUCENT@> + packDeferredFragmentUnlit(vec3(1.0, 0.0, 0.0), 1.0, _color.rgb); + <@else@> + packDeferredFragmentTranslucent(vec3(1.0, 0.0, 0.0), _color.a, _color.rgb, DEFAULT_ROUGHNESS); + <@endif@> +<@else@> + _fragColor0 = _color; +<@endif@> } diff --git a/libraries/render-utils/src/parabola_translucent.slf b/libraries/render-utils/src/parabola_translucent.slf deleted file mode 100644 index 01f4614172..0000000000 --- a/libraries/render-utils/src/parabola_translucent.slf +++ /dev/null @@ -1,18 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 9/10/2018 -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> - -layout(location=0) in vec4 _color; - -void main(void) { - packDeferredFragmentTranslucent(vec3(1.0, 0.0, 0.0), _color.a, _color.rgb, DEFAULT_ROUGHNESS); -} diff --git a/libraries/render-utils/src/render-utils/deformed_model.slp b/libraries/render-utils/src/render-utils/deformed_model.slp deleted file mode 100644 index 9db8938e86..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT model diff --git a/libraries/render-utils/src/render-utils/deformed_model_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_dq.slp deleted file mode 100644 index ec950ac784..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT model diff --git a/libraries/render-utils/src/render-utils/deformed_model_fade.slp b/libraries/render-utils/src/render-utils/deformed_model_fade.slp deleted file mode 100644 index 5818e5e3af..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_fade.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT model_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_fade_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_fade_dq.slp deleted file mode 100644 index 9047bc1286..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_fade_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT model_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map.slp deleted file mode 100644 index ad460652ad..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT model_normal_map diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_dq.slp deleted file mode 100644 index 44d5cd5272..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT model_normal_map diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade.slp deleted file mode 100644 index 99aab59169..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT model_normal_map_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade_dq.slp deleted file mode 100644 index 0ee002b6a1..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT model_normal_map_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent.slp deleted file mode 100644 index f2e2b2e4da..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT model_translucent_normal_map diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_dq.slp deleted file mode 100644 index 577a6c1616..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT model_translucent_normal_map diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade.slp deleted file mode 100644 index de9591b45f..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT model_translucent_normal_map_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade_dq.slp deleted file mode 100644 index 3f624f7bf7..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT model_translucent_normal_map_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_shadow.slp b/libraries/render-utils/src/render-utils/deformed_model_shadow.slp deleted file mode 100644 index c8718dff09..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_shadow.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_shadow -FRAGMENT model_shadow diff --git a/libraries/render-utils/src/render-utils/deformed_model_shadow_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_shadow_dq.slp deleted file mode 100644 index b0f1449234..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_shadow_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_shadow_dq -FRAGMENT model_shadow diff --git a/libraries/render-utils/src/render-utils/deformed_model_shadow_fade.slp b/libraries/render-utils/src/render-utils/deformed_model_shadow_fade.slp deleted file mode 100644 index 1063134d96..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_shadow_fade.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_shadow -FRAGMENT model_shadow_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_shadow_fade_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_shadow_fade_dq.slp deleted file mode 100644 index 25c99c75d1..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_shadow_fade_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_shadow_dq -FRAGMENT model_shadow_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_translucent.slp b/libraries/render-utils/src/render-utils/deformed_model_translucent.slp deleted file mode 100644 index 798fec9a5b..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_translucent.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT model_translucent diff --git a/libraries/render-utils/src/render-utils/deformed_model_translucent_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_translucent_dq.slp deleted file mode 100644 index 8a0b70cfcf..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_translucent_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT model_translucent diff --git a/libraries/render-utils/src/render-utils/deformed_model_translucent_fade.slp b/libraries/render-utils/src/render-utils/deformed_model_translucent_fade.slp deleted file mode 100644 index 68eef3624d..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_translucent_fade.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT model_translucent_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_translucent_fade_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_translucent_fade_dq.slp deleted file mode 100644 index 4ce321fa78..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_translucent_fade_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT model_translucent_fade diff --git a/libraries/render-utils/src/render-utils/forward_deformed_model.slp b/libraries/render-utils/src/render-utils/forward_deformed_model.slp deleted file mode 100644 index 3b7c49705b..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_model.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT forward_model diff --git a/libraries/render-utils/src/render-utils/forward_deformed_model_dq.slp b/libraries/render-utils/src/render-utils/forward_deformed_model_dq.slp deleted file mode 100644 index 45d886529a..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_model_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT forward_model diff --git a/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map.slp b/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map.slp deleted file mode 100644 index 539ca61193..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT forward_model_normal_map diff --git a/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map_dq.slp b/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map_dq.slp deleted file mode 100644 index c663b671fe..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT forward_model_normal_map diff --git a/libraries/render-utils/src/render-utils/forward_deformed_translucent.slp b/libraries/render-utils/src/render-utils/forward_deformed_translucent.slp deleted file mode 100644 index 605499ebc3..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_translucent.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT forward_model_translucent diff --git a/libraries/render-utils/src/render-utils/forward_deformed_translucent_dq.slp b/libraries/render-utils/src/render-utils/forward_deformed_translucent_dq.slp deleted file mode 100644 index cd20657b01..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_translucent_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT forward_model_translucent diff --git a/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map.slp b/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map.slp deleted file mode 100644 index 85d08c1943..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT forward_model_translucent diff --git a/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map_dq.slp b/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map_dq.slp deleted file mode 100644 index 2f13b16a5b..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT forward_model_translucent diff --git a/libraries/render-utils/src/render-utils/forward_grid.slp b/libraries/render-utils/src/render-utils/forward_grid.slp deleted file mode 100644 index c81b208f63..0000000000 --- a/libraries/render-utils/src/render-utils/forward_grid.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX standardTransformPNTC diff --git a/libraries/render-utils/src/render-utils/forward_grid_translucent.slp b/libraries/render-utils/src/render-utils/forward_grid_translucent.slp deleted file mode 100644 index c81b208f63..0000000000 --- a/libraries/render-utils/src/render-utils/forward_grid_translucent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX standardTransformPNTC diff --git a/libraries/render-utils/src/render-utils/forward_model.slp b/libraries/render-utils/src/render-utils/forward_model.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/forward_model_lightmap.slp b/libraries/render-utils/src/render-utils/forward_model_lightmap.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_lightmap.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/forward_model_normal_map.slp b/libraries/render-utils/src/render-utils/forward_model_normal_map.slp deleted file mode 100644 index c50be6285b..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_normal_map.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map diff --git a/libraries/render-utils/src/render-utils/forward_model_normal_map_lightmap.slp b/libraries/render-utils/src/render-utils/forward_model_normal_map_lightmap.slp deleted file mode 100644 index c50be6285b..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_normal_map_lightmap.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map diff --git a/libraries/render-utils/src/render-utils/forward_model_normal_map_translucent.slp b/libraries/render-utils/src/render-utils/forward_model_normal_map_translucent.slp deleted file mode 100644 index 0979918b98..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_normal_map_translucent.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX model_normal_map -FRAGMENT forward_model_translucent diff --git a/libraries/render-utils/src/render-utils/forward_model_translucent.slp b/libraries/render-utils/src/render-utils/forward_model_translucent.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_translucent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/forward_model_unlit.slp b/libraries/render-utils/src/render-utils/forward_model_unlit.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/forward_parabola.slp b/libraries/render-utils/src/render-utils/forward_parabola.slp deleted file mode 100644 index ab3f1d4126..0000000000 --- a/libraries/render-utils/src/render-utils/forward_parabola.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX parabola diff --git a/libraries/render-utils/src/render-utils/forward_sdf_text3D.slp b/libraries/render-utils/src/render-utils/forward_sdf_text3D.slp deleted file mode 100644 index 3eea3a0da0..0000000000 --- a/libraries/render-utils/src/render-utils/forward_sdf_text3D.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX sdf_text3D diff --git a/libraries/render-utils/src/render-utils/forward_simple_textured.slp b/libraries/render-utils/src/render-utils/forward_simple_textured.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/forward_simple_textured.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/forward_simple_textured_transparent.slp b/libraries/render-utils/src/render-utils/forward_simple_textured_transparent.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/forward_simple_textured_transparent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/forward_simple_textured_unlit.slp b/libraries/render-utils/src/render-utils/forward_simple_textured_unlit.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/forward_simple_textured_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/glowLine.slp b/libraries/render-utils/src/render-utils/glowLine.slp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libraries/render-utils/src/render-utils/grid.slp b/libraries/render-utils/src/render-utils/grid.slp index c81b208f63..5cf10ff674 100644 --- a/libraries/render-utils/src/render-utils/grid.slp +++ b/libraries/render-utils/src/render-utils/grid.slp @@ -1 +1,2 @@ VERTEX standardTransformPNTC +DEFINES translucent:f forward:f \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/grid_translucent.slp b/libraries/render-utils/src/render-utils/grid_translucent.slp deleted file mode 100644 index c81b208f63..0000000000 --- a/libraries/render-utils/src/render-utils/grid_translucent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX standardTransformPNTC diff --git a/libraries/render-utils/src/render-utils/model.slp b/libraries/render-utils/src/render-utils/model.slp index e69de29bb2..b63ec898eb 100644 --- a/libraries/render-utils/src/render-utils/model.slp +++ b/libraries/render-utils/src/render-utils/model.slp @@ -0,0 +1 @@ +DEFINES (normalmap translucent:f unlit:f/lightmap:f)/shadow fade:f/forward:f deformed:v/deformeddq:v \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_fade.slp b/libraries/render-utils/src/render-utils/model_fade.slp deleted file mode 100644 index ea0b2cf566..0000000000 --- a/libraries/render-utils/src/render-utils/model_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_lightmap.slp b/libraries/render-utils/src/render-utils/model_lightmap.slp deleted file mode 100644 index ea0b2cf566..0000000000 --- a/libraries/render-utils/src/render-utils/model_lightmap.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_lightmap_fade.slp b/libraries/render-utils/src/render-utils/model_lightmap_fade.slp deleted file mode 100644 index ea0b2cf566..0000000000 --- a/libraries/render-utils/src/render-utils/model_lightmap_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_lightmap_normal_map.slp b/libraries/render-utils/src/render-utils/model_lightmap_normal_map.slp deleted file mode 100644 index c50be6285b..0000000000 --- a/libraries/render-utils/src/render-utils/model_lightmap_normal_map.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map diff --git a/libraries/render-utils/src/render-utils/model_lightmap_normal_map_fade.slp b/libraries/render-utils/src/render-utils/model_lightmap_normal_map_fade.slp deleted file mode 100644 index 659899f9f8..0000000000 --- a/libraries/render-utils/src/render-utils/model_lightmap_normal_map_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_normal_map.slp b/libraries/render-utils/src/render-utils/model_normal_map.slp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libraries/render-utils/src/render-utils/model_normal_map_fade.slp b/libraries/render-utils/src/render-utils/model_normal_map_fade.slp deleted file mode 100644 index 659899f9f8..0000000000 --- a/libraries/render-utils/src/render-utils/model_normal_map_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_shadow.slp b/libraries/render-utils/src/render-utils/model_shadow.slp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libraries/render-utils/src/render-utils/model_shadow_fade.slp b/libraries/render-utils/src/render-utils/model_shadow_fade.slp deleted file mode 100644 index f43521cba6..0000000000 --- a/libraries/render-utils/src/render-utils/model_shadow_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_shadow \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_translucent.slp b/libraries/render-utils/src/render-utils/model_translucent.slp deleted file mode 100644 index ea0b2cf566..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_translucent_fade.slp b/libraries/render-utils/src/render-utils/model_translucent_fade.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/model_translucent_normal_map.slp b/libraries/render-utils/src/render-utils/model_translucent_normal_map.slp deleted file mode 100644 index 659899f9f8..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent_normal_map.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_translucent_normal_map_fade.slp b/libraries/render-utils/src/render-utils/model_translucent_normal_map_fade.slp deleted file mode 100644 index c50be6285b..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent_normal_map_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map diff --git a/libraries/render-utils/src/render-utils/model_translucent_unlit.slp b/libraries/render-utils/src/render-utils/model_translucent_unlit.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/model_translucent_unlit_fade.slp b/libraries/render-utils/src/render-utils/model_translucent_unlit_fade.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent_unlit_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/model_unlit.slp b/libraries/render-utils/src/render-utils/model_unlit.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/model_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/model_unlit_fade.slp b/libraries/render-utils/src/render-utils/model_unlit_fade.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/model_unlit_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/parabola.slp b/libraries/render-utils/src/render-utils/parabola.slp index e69de29bb2..e9942be5cd 100644 --- a/libraries/render-utils/src/render-utils/parabola.slp +++ b/libraries/render-utils/src/render-utils/parabola.slp @@ -0,0 +1 @@ +DEFINES translucent:f/forward:f \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/parabola_translucent.slp b/libraries/render-utils/src/render-utils/parabola_translucent.slp deleted file mode 100644 index ab3f1d4126..0000000000 --- a/libraries/render-utils/src/render-utils/parabola_translucent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX parabola diff --git a/libraries/render-utils/src/render-utils/sdf_text3D.slp b/libraries/render-utils/src/render-utils/sdf_text3D.slp index e69de29bb2..06d27fe4ce 100644 --- a/libraries/render-utils/src/render-utils/sdf_text3D.slp +++ b/libraries/render-utils/src/render-utils/sdf_text3D.slp @@ -0,0 +1 @@ +DEFINES translucent forward \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/sdf_text3D_transparent.slp b/libraries/render-utils/src/render-utils/sdf_text3D_transparent.slp deleted file mode 100644 index 3eea3a0da0..0000000000 --- a/libraries/render-utils/src/render-utils/sdf_text3D_transparent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX sdf_text3D diff --git a/libraries/render-utils/src/render-utils/simple.slp b/libraries/render-utils/src/render-utils/simple.slp index e69de29bb2..5fc7789a21 100644 --- a/libraries/render-utils/src/render-utils/simple.slp +++ b/libraries/render-utils/src/render-utils/simple.slp @@ -0,0 +1 @@ +DEFINES translucent unlit fade/forward \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/simple_opaque_web_browser.slp b/libraries/render-utils/src/render-utils/simple_opaque_web_browser.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_opaque_web_browser.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_procedural.slp b/libraries/render-utils/src/render-utils/simple_procedural.slp new file mode 100644 index 0000000000..1348d72a8d --- /dev/null +++ b/libraries/render-utils/src/render-utils/simple_procedural.slp @@ -0,0 +1 @@ +DEFINES translucent:f \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/simple_textured.slp b/libraries/render-utils/src/render-utils/simple_textured.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_textured.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_textured_fade.slp b/libraries/render-utils/src/render-utils/simple_textured_fade.slp deleted file mode 100644 index 9be0f525ad..0000000000 --- a/libraries/render-utils/src/render-utils/simple_textured_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple_fade diff --git a/libraries/render-utils/src/render-utils/simple_textured_unlit.slp b/libraries/render-utils/src/render-utils/simple_textured_unlit.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_textured_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_textured_unlit_fade.slp b/libraries/render-utils/src/render-utils/simple_textured_unlit_fade.slp deleted file mode 100644 index 9be0f525ad..0000000000 --- a/libraries/render-utils/src/render-utils/simple_textured_unlit_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple_fade diff --git a/libraries/render-utils/src/render-utils/simple_transparent.slp b/libraries/render-utils/src/render-utils/simple_transparent.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_transparent_textured.slp b/libraries/render-utils/src/render-utils/simple_transparent_textured.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent_textured.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_transparent_textured_fade.slp b/libraries/render-utils/src/render-utils/simple_transparent_textured_fade.slp deleted file mode 100644 index 9be0f525ad..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent_textured_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple_fade diff --git a/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit.slp b/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit_fade.slp b/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit_fade.slp deleted file mode 100644 index 9be0f525ad..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple_fade diff --git a/libraries/render-utils/src/render-utils/simple_transparent_web_browser.slp b/libraries/render-utils/src/render-utils/simple_transparent_web_browser.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent_web_browser.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/web_browser.slp b/libraries/render-utils/src/render-utils/web_browser.slp new file mode 100644 index 0000000000..e9942be5cd --- /dev/null +++ b/libraries/render-utils/src/render-utils/web_browser.slp @@ -0,0 +1 @@ +DEFINES translucent:f/forward:f \ No newline at end of file diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index 91c73e9eec..ab67447d04 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -1,8 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> -// sdf_text3D.frag -// fragment shader // // Created by Bradley Austin Davis on 2015-02-04 // Based on fragment shader code from @@ -10,12 +9,32 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -<@include DeferredBufferWrite.slh@> +<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + <@include DefaultMaterials.slh@> + + <@include GlobalLight.slh@> + <@if HIFI_USE_FORWARD@> + <$declareEvalSkyboxGlobalColor()$> + <@else@> + <$declareEvalGlobalLightingAlphaBlendedWithHaze()$> + <@endif@> + + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + + layout(location=0) out vec4 _fragColor0; +<@else@> + <@include DeferredBufferWrite.slh@> +<@endif@> + <@include render-utils/ShaderConstants.h@> <@include sdf_text3D.slh@> <$declareEvalSDFSuperSampled()$> +<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; +<@endif@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; @@ -23,15 +42,56 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord1 _texCoord01.zw void main() { - float a = evalSDFSuperSampled(_texCoord0); + float alpha = evalSDFSuperSampled(_texCoord0); + +<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + alpha *= _color.a; + if (alpha <= 0.0) { + discard; + } + + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _positionES.xyz; + + <@if HIFI_USE_FORWARD@> + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normalWS), + _color.rgb, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_ROUGHNESS), + alpha); + <@else@> + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normalWS), + _color.rgb, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_ROUGHNESS, alpha), + alpha); + <@endif@> +<@else@> + if (alpha <= 0.0) { + discard; + } packDeferredFragment( normalize(_normalWS), - a, + alpha, _color.rgb, DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION, DEFAULT_SCATTERING); +<@endif@> } \ No newline at end of file diff --git a/libraries/render-utils/src/sdf_text3D.slv b/libraries/render-utils/src/sdf_text3D.slv index 274e09e6ad..731cbc2cad 100644 --- a/libraries/render-utils/src/sdf_text3D.slv +++ b/libraries/render-utils/src/sdf_text3D.slv @@ -19,20 +19,25 @@ <@include sdf_text3D.slh@> -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; +<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; +<@endif@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; void main() { - _texCoord01.xy = inTexCoord0.xy; + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); _color = color_sRGBAToLinear(params.color); - - // standard transform + TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); +<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> +<@else@> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> +<@endif@> + const vec3 normal = vec3(0, 0, 1); <$transformModelToWorldDir(cam, obj, normal, _normalWS)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/sdf_text3D_transparent.slf b/libraries/render-utils/src/sdf_text3D_transparent.slf deleted file mode 100644 index c4a80091de..0000000000 --- a/libraries/render-utils/src/sdf_text3D_transparent.slf +++ /dev/null @@ -1,58 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// sdf_text3D_transparent.frag -// fragment shader -// -// Created by Bradley Austin Davis on 2015-02-04 -// Based on fragment shader code from -// https://github.com/paulhoux/Cinder-Samples/blob/master/TextRendering/include/text/Text.cpp -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -<@include DefaultMaterials.slh@> - -<@include ForwardGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include render-utils/ShaderConstants.h@> - -<@include sdf_text3D.slh@> -<$declareEvalSDFSuperSampled()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -layout(location=0) out vec4 _fragColor0; - -void main() { - float a = evalSDFSuperSampled(_texCoord0); - - float alpha = a * _color.a; - if (alpha <= 0.0) { - discard; - } - - TransformCamera cam = getTransformCamera(); - vec3 fragPosition = _positionES.xyz; - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS), - _color.rgb, - DEFAULT_FRESNEL, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE, - DEFAULT_ROUGHNESS, alpha), - alpha); -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 469c0976aa..5585c9a7d1 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -1,10 +1,8 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // -// simple.frag -// fragment shader -// // Created by Andrzej Kapolka on 9/15/14. // Copyright 2014 High Fidelity, Inc. // @@ -12,133 +10,144 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBufferWrite.slh@> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - +<@include gpu/Color.slh@> +<@include DefaultMaterials.slh@> <@include render-utils/ShaderConstants.h@> -// the interpolated normal +<@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + <@if not HIFI_USE_UNLIT@> + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + <@else@> + <@include LightingModel.slh@> +<@endif@> + + layout(location=0) out vec4 _fragColor0; +<@endif@> + +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_FORWARD@> + <@include GlobalLight.slh@> + <$declareEvalSkyboxGlobalColor()$> + <@elif HIFI_USE_TRANSLUCENT@> + <@include GlobalLight.slh@> + <$declareEvalGlobalLightingAlphaBlendedWithHaze()$> + <@else@> + <@include DeferredBufferWrite.slh@> + <@endif@> +<@else@> + <@if not HIFI_USE_FORWARD@> + <@if not HIFI_USE_TRANSLUCENT@> + <@include DeferredBufferWrite.slh@> + <@endif@> + <@endif@> +<@endif@> + +<@if HIFI_USE_FADE@> + <@include Fade.slh@> + <$declareFadeFragmentInstanced()$> +<@endif@> + +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; + <@endif@> +<@endif@> +<@if HIFI_USE_FADE@> + layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; +<@endif@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normalMS; layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy #define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _positionMS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -// For retro-compatibility -#define _normal _normalWS -#define _modelNormal _normalMS -#define _position _positionMS -#define _eyePosition _positionES +LAYOUT(binding=0) uniform sampler2D simpleTexture; -<@include procedural/ProceduralCommon.slh@> - -#line 1001 -//PROCEDURAL_BLOCK_BEGIN - -vec3 getProceduralColor() { - return _color.rgb; -} - -float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) { - return 1.0; -} - -float getProceduralFragment(inout ProceduralFragment proceduralData) { - return 1.0; -} - -float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition proceduralData) { - return 1.0; -} - -//PROCEDURAL_BLOCK_END - -#line 2030 void main(void) { - vec3 normal = normalize(_normalWS.xyz); - vec3 diffuse = _color.rgb; - float roughness = DEFAULT_ROUGHNESS; - float metallic = DEFAULT_METALLIC; - vec3 emissive = DEFAULT_EMISSIVE; - float occlusion = DEFAULT_OCCLUSION; - float scattering = DEFAULT_SCATTERING; + vec4 texel = texture(simpleTexture, _texCoord0); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); + texel.rgb *= _color.rgb; + texel.a *= abs(_color.a); - float emissiveAmount = 0.0; +<@if HIFI_USE_FADE@> + vec3 fadeEmissive; + FadeObjectParams fadeParams; + <$fetchFadeObjectParamsInstanced(fadeParams)$> + applyFade(fadeParams, _positionWS.xyz, fadeEmissive); +<@endif@> -#if defined(PROCEDURAL_V1) - diffuse = getProceduralColor().rgb; - emissiveAmount = 1.0; - emissive = vec3(1.0); -#elif defined(PROCEDURAL_V2) - vec3 specular = DEFAULT_SPECULAR; - float shininess = DEFAULT_SHININESS; - emissiveAmount = getProceduralColors(diffuse, specular, shininess); - roughness = max(0.0, 1.0 - shininess / 128.0); - metallic = length(specular); - emissive = vec3(clamp(emissiveAmount, 0.0, 1.0)); -#elif defined(PROCEDURAL_V3) || defined(PROCEDURAL_V4) -#if defined(PROCEDURAL_V3) - ProceduralFragment proceduralData = ProceduralFragment( -#else - TransformCamera cam = getTransformCamera(); - vec4 position = cam._viewInverse * _positionES; - ProceduralFragmentWithPosition proceduralData = ProceduralFragmentWithPosition( - position.xyz, -#endif - normal, - diffuse, - DEFAULT_SPECULAR, - emissive, - 1.0, - roughness, - metallic, - occlusion, - scattering - ); +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + float metallic = DEFAULT_METALLIC; + vec3 fresnel = getFresnelF0(metallic, texel.rgb); -#if defined(PROCEDURAL_V3) - emissiveAmount = getProceduralFragment(proceduralData); -#else - emissiveAmount = getProceduralFragmentWithPosition(proceduralData); -#endif - normal = proceduralData.normal; - diffuse = proceduralData.diffuse; - roughness = proceduralData.roughness; - metallic = proceduralData.metallic; - emissive = proceduralData.emissive; - occlusion = proceduralData.occlusion; - scattering = proceduralData.scattering; + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _positionES.xyz; + <@endif@> +<@endif@> -#if defined(PROCEDURAL_V4) - position = vec4(proceduralData.position, 1.0); - vec4 posClip = cam._projection * (cam._view * position); - gl_FragDepth = 0.5 * (posClip.z / posClip.w + 1.0); -#endif - -#endif - - if (emissiveAmount > 0.0) { - packDeferredFragmentLightmap( - normal, +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_FORWARD@> + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, 1.0, - diffuse, - roughness, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normalWS), + texel.rgb, + fresnel, metallic, - emissive); - } else { + DEFAULT_ROUGHNESS), + texel.a); + <@elif HIFI_USE_TRANSLUCENT@> + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normalWS), + texel.rgb, + fresnel, + metallic, + DEFAULT_EMISSIVE + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , + DEFAULT_ROUGHNESS, texel.a), + texel.a); + <@else@> packDeferredFragment( - normal, + normalize(_normalWS), 1.0, - diffuse, - roughness, - metallic, - emissive, - occlusion, - scattering); - } + texel.rgb, + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); + <@endif@> +<@else@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + _fragColor0 = isUnlitEnabled() * vec4(texel.rgb + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , texel.a); + <@else@> + packDeferredFragmentUnlit( + normalize(_normalWS), + 1.0, + texel.rgb + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + ); + <@endif@> +<@endif@> } diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index 460ed53281..f766acceda 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -1,10 +1,8 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // -// simple.vert -// vertex shader -// // Created by Andrzej Kapolka on 9/15/14. // Copyright 2014 High Fidelity, Inc. // @@ -19,22 +17,36 @@ <@include render-utils/ShaderConstants.h@> +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; + <@endif@> +<@endif@> +<@if HIFI_USE_FADE@> + layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; +<@endif@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _positionMS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; void main(void) { _color = color_sRGBAToLinear(inColor); - _texCoord01.xy = inTexCoord0.st; - _positionMS = inPosition; - _normalMS = inNormal.xyz; + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> + <@else@> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <@endif@> +<@else@> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> +<@endif@> + +<@if HIFI_USE_FADE@> + <$transformModelToWorldPos(obj, inPosition, _positionWS)$> +<@endif@> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent.slf b/libraries/render-utils/src/simple_procedural.slf similarity index 79% rename from libraries/render-utils/src/simple_transparent.slf rename to libraries/render-utils/src/simple_procedural.slf index 6d8348f50c..ef588c4651 100644 --- a/libraries/render-utils/src/simple_transparent.slf +++ b/libraries/render-utils/src/simple_procedural.slf @@ -1,37 +1,39 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // -// simple_transparent.frag -// fragment shader -// // Created by Andrzej Kapolka on 9/15/14. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DefaultMaterials.slh@> -<@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> +<@if not HIFI_USE_TRANSLUCENT@> + <@include DeferredBufferWrite.slh@> +<@else@> + <@include DefaultMaterials.slh@> + + <@include GlobalLight.slh@> + <$declareEvalGlobalLightingAlphaBlendedWithHaze()$> + + layout(location=0) out vec4 _fragColor0; +<@endif@> <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> <@include render-utils/ShaderConstants.h@> -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; +layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _positionMS; +layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normalMS; +layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy #define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _positionMS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; - -layout(location=0) out vec4 _fragColor0; // For retro-compatibility #define _normal _normalWS @@ -42,7 +44,6 @@ layout(location=0) out vec4 _fragColor0; <@include procedural/ProceduralCommon.slh@> #line 1001 - //PROCEDURAL_BLOCK_BEGIN vec3 getProceduralColor() { @@ -67,19 +68,24 @@ float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition pro void main(void) { vec3 normal = normalize(_normalWS.xyz); vec3 diffuse = _color.rgb; - float alpha = _color.a; - float occlusion = DEFAULT_OCCLUSION; vec3 fresnel = DEFAULT_FRESNEL; + float roughness = DEFAULT_ROUGHNESS; float metallic = DEFAULT_METALLIC; vec3 emissive = DEFAULT_EMISSIVE; - float roughness = DEFAULT_ROUGHNESS; + float occlusion = DEFAULT_OCCLUSION; + float scattering = DEFAULT_SCATTERING; float emissiveAmount = 0.0; +<@if HIFI_USE_TRANSLUCENT@> + float alpha = _color.a; TransformCamera cam = getTransformCamera(); vec3 posEye = _positionES.xyz; +<@else@> + float alpha = 1.0; +<@endif@> -#ifdef PROCEDURAL_V1 +#if defined(PROCEDURAL_V1) diffuse = getProceduralColor().rgb; emissiveAmount = 1.0; emissive = vec3(1.0); @@ -94,6 +100,7 @@ void main(void) { #if defined(PROCEDURAL_V3) ProceduralFragment proceduralData = ProceduralFragment( #else + TransformCamera cam = getTransformCamera(); vec4 position = cam._viewInverse * _positionES; ProceduralFragmentWithPosition proceduralData = ProceduralFragmentWithPosition( position.xyz, @@ -106,7 +113,7 @@ void main(void) { roughness, metallic, occlusion, - DEFAULT_SCATTERING + scattering ); #if defined(PROCEDURAL_V3) @@ -114,25 +121,49 @@ void main(void) { #else emissiveAmount = getProceduralFragmentWithPosition(proceduralData); #endif - occlusion = proceduralData.occlusion; normal = proceduralData.normal; diffuse = proceduralData.diffuse; fresnel = proceduralData.specular; + roughness = proceduralData.roughness; metallic = proceduralData.metallic; emissive = proceduralData.emissive; - roughness = proceduralData.roughness; + occlusion = proceduralData.occlusion; + scattering = proceduralData.scattering; alpha = proceduralData.alpha; #if defined(PROCEDURAL_V4) position = vec4(proceduralData.position, 1.0); vec4 posEye4 = cam._view * position; +<@if HIFI_USE_TRANSLUCENT@> posEye = posEye4.xyz; +<@endif@> vec4 posClip = cam._projection * posEye4; gl_FragDepth = 0.5 * (posClip.z / posClip.w + 1.0); #endif #endif +<@if not HIFI_USE_TRANSLUCENT@> + if (emissiveAmount > 0.0) { + packDeferredFragmentLightmap( + normal, + 1.0, + diffuse, + roughness, + metallic, + emissive); + } else { + packDeferredFragment( + normal, + 1.0, + diffuse, + roughness, + metallic, + emissive, + occlusion, + scattering); + } +<@else@> if (emissiveAmount > 0.0) { _fragColor0 = vec4(diffuse, alpha); } else { @@ -149,4 +180,5 @@ void main(void) { roughness, alpha), alpha); } +<@endif@> } diff --git a/libraries/render-utils/src/simple_fade.slv b/libraries/render-utils/src/simple_procedural.slv similarity index 70% rename from libraries/render-utils/src/simple_fade.slv rename to libraries/render-utils/src/simple_procedural.slv index 0bbd8eac39..181afa50bd 100644 --- a/libraries/render-utils/src/simple_fade.slv +++ b/libraries/render-utils/src/simple_procedural.slv @@ -1,12 +1,10 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> +// <$_SCRIBE_FILENAME$> +// Generated on <$_SCRIBE_DATE$> // -// simple_fade.vert -// vertex shader -// -// Created by Olivier Prat on 06/04/17. -// Copyright 2017 High Fidelity, Inc. +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -17,31 +15,23 @@ <@include gpu/Transform.slh@> <$declareStandardTransform()$> -<@include Fade.slh@> -<$declareFadeVertexInstanced()$> - <@include render-utils/ShaderConstants.h@> -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _positionMS; layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; +layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; +layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; +layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; +layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; void main(void) { _color = color_sRGBAToLinear(inColor); - _texCoord01.xy = inTexCoord0.st; + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); _positionMS = inPosition; _normalMS = inNormal.xyz; - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> - <$transformModelToWorldPos(obj, inPosition, _positionWS)$> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> - <$passThroughFadeObjectParams()$> } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf deleted file mode 100644 index dbc49fcb5d..0000000000 --- a/libraries/render-utils/src/simple_textured.slf +++ /dev/null @@ -1,44 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_textured.frag -// fragment shader -// -// Created by Clement Brisset on 5/29/15. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - - packDeferredFragment( - normalize(_normalWS), - 1.0, - texel.rgb, - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf deleted file mode 100644 index 5a9eb0688e..0000000000 --- a/libraries/render-utils/src/simple_textured_fade.slf +++ /dev/null @@ -1,66 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_textured_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - -<@include Fade.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -// Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragmentInstanced()$> - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParamsInstanced(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - const float ALPHA_THRESHOLD = 0.999; - if (texel.a < ALPHA_THRESHOLD) { - packDeferredFragmentTranslucent( - normalize(_normalWS), - texel.a, - texel.rgb + fadeEmissive, - DEFAULT_ROUGHNESS); - } else { - packDeferredFragment( - normalize(_normalWS), - 1.0, - texel.rgb, - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE + fadeEmissive, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); - } -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_unlit.slf b/libraries/render-utils/src/simple_textured_unlit.slf deleted file mode 100644 index 475428f0ae..0000000000 --- a/libraries/render-utils/src/simple_textured_unlit.slf +++ /dev/null @@ -1,49 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_textured_unlit.frag -// fragment shader -// -// Created by Clement Brisset on 5/29/15. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - const float ALPHA_THRESHOLD = 0.999; - if (texel.a < ALPHA_THRESHOLD) { - packDeferredFragmentTranslucent( - normalize(_normalWS), - texel.a, - texel.rgb, - DEFAULT_ROUGHNESS); - } else { - packDeferredFragmentUnlit( - normalize(_normalWS), - 1.0, - texel.rgb); - } -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_unlit_fade.slf b/libraries/render-utils/src/simple_textured_unlit_fade.slf deleted file mode 100644 index d0ba4c13fe..0000000000 --- a/libraries/render-utils/src/simple_textured_unlit_fade.slf +++ /dev/null @@ -1,61 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_textured_unlit_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - -<@include Fade.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -// Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragmentInstanced()$> - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParamsInstanced(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - const float ALPHA_THRESHOLD = 0.999; - if (texel.a < ALPHA_THRESHOLD) { - packDeferredFragmentTranslucent( - normalize(_normalWS), - texel.a, - texel.rgb + fadeEmissive, - DEFAULT_ROUGHNESS); - } else { - packDeferredFragmentUnlit( - normalize(_normalWS), - 1.0, - texel.rgb + fadeEmissive); - } -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf deleted file mode 100644 index 9f8a88c7c2..0000000000 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ /dev/null @@ -1,60 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_transparent_textured.frag -// fragment shader -// -// Created by Sam Gateau on 4/3/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -<@include DefaultMaterials.slh@> - -<@include gpu/Color.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - vec3 albedo = _color.xyz * texel.xyz; - float alpha = _color.a * texel.a; - float metallic = DEFAULT_METALLIC; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - TransformCamera cam = getTransformCamera(); - vec3 fragPosition = _positionES.xyz; - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS), - albedo, - fresnel, - metallic, - DEFAULT_EMISSIVE, - DEFAULT_ROUGHNESS, alpha), - alpha); -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf deleted file mode 100644 index d401989f90..0000000000 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ /dev/null @@ -1,72 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_transparent_textured_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Color.slh@> - -<@include DeferredBufferWrite.slh@> -<@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include Fade.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -// Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragmentInstanced()$> - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParamsInstanced(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - vec3 fragPosition = _positionES.xyz; - vec3 fragNormal = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - 1.0, - fragPosition, - fragNormal, - texel.rgb, - DEFAULT_FRESNEL, - 0.0f, - fadeEmissive, - DEFAULT_ROUGHNESS, - texel.a), - texel.a); -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit.slf b/libraries/render-utils/src/simple_transparent_textured_unlit.slf deleted file mode 100644 index 42a8270274..0000000000 --- a/libraries/render-utils/src/simple_transparent_textured_unlit.slf +++ /dev/null @@ -1,36 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_transparent_textured_unlit.frag -// fragment shader -// -// Created by Sam Gateau on 4/3/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Color.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - _fragColor0 = texel; -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf deleted file mode 100644 index afc0c94575..0000000000 --- a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf +++ /dev/null @@ -1,48 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_transparent_textured_unlit_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Color.slh@> - -<@include Fade.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -layout(location=0) out vec4 _fragColor0; - -// Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragmentInstanced()$> - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParamsInstanced(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - _fragColor0 = vec4(texel.rgb + fadeEmissive, texel.a); -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_web_browser.slf b/libraries/render-utils/src/simple_transparent_web_browser.slf deleted file mode 100644 index 599fd3d87f..0000000000 --- a/libraries/render-utils/src/simple_transparent_web_browser.slf +++ /dev/null @@ -1,38 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_transparent_web_browser.frag -// fragment shader -// -// Created by Anthony Thibault on 7/25/16. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = color_sRGBAToLinear(texel); - packDeferredFragmentTranslucent( - normalize(_normalWS), - _color.a * texel.a, - _color.rgb * texel.rgb, - DEFAULT_ROUGHNESS); -} diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index c69db5e055..eec65ddf44 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -233,7 +233,7 @@ void Font::setupGPU() { gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); PrepareStencil::testMaskDrawShape(*state); _deferredPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D), state); - _forwardPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::forward_sdf_text3D), state); + _forwardPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_forward), state); } { @@ -244,7 +244,7 @@ void Font::setupGPU() { gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); PrepareStencil::testMask(*state); - _transparentPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_transparent), state); + _transparentPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_translucent), state); } } diff --git a/libraries/render-utils/src/simple_opaque_web_browser.slf b/libraries/render-utils/src/web_browser.slf similarity index 54% rename from libraries/render-utils/src/simple_opaque_web_browser.slf rename to libraries/render-utils/src/web_browser.slf index df789ee22b..7898df1c4c 100644 --- a/libraries/render-utils/src/simple_opaque_web_browser.slf +++ b/libraries/render-utils/src/web_browser.slf @@ -1,10 +1,8 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // -// simple_opaque_web_browser.frag -// fragment shader -// // Created by Anthony Thibault on 7/25/16. // Copyright 2016 High Fidelity, Inc. // @@ -13,14 +11,16 @@ // <@include gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - <@include render-utils/ShaderConstants.h@> -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; +<@if not HIFI_USE_FORWARD@> + <@include DeferredBufferWrite.slh@> +<@else@> + layout(location=0) out vec4 _fragColor0; +<@endif@> + +LAYOUT(binding=0) uniform sampler2D webTexture; -// the interpolated normal layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; @@ -28,7 +28,17 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord1 _texCoord01.zw void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); + vec4 texel = texture(webTexture, _texCoord0); texel = color_sRGBAToLinear(texel); - packDeferredFragmentUnlit(normalize(_normalWS), 1.0, _color.rgb * texel.rgb); + texel *= _color; + +<@if not HIFI_USE_FORWARD@> + <@if not HIFI_USE_TRANSLUCENT@> + packDeferredFragmentUnlit(normalize(_normalWS), 1.0, texel.rgb); + <@else@> + packDeferredFragmentTranslucent(normalize(_normalWS), texel.a, texel.rgb, DEFAULT_ROUGHNESS); + <@endif@> +<@else@> + _fragColor0 = texel; +<@endif@> } diff --git a/libraries/render-utils/src/web_browser.slv b/libraries/render-utils/src/web_browser.slv new file mode 100644 index 0000000000..019486fbf3 --- /dev/null +++ b/libraries/render-utils/src/web_browser.slv @@ -0,0 +1,32 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> +// Generated on <$_SCRIBE_DATE$> +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include render-utils/ShaderConstants.h@> + +layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; +layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; +layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; + +void main(void) { + _color = color_sRGBAToLinear(inColor); + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); + + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> +} \ No newline at end of file diff --git a/tools/shadergen.py b/tools/shadergen.py index f82b471f17..1f4acae915 100644 --- a/tools/shadergen.py +++ b/tools/shadergen.py @@ -66,7 +66,6 @@ def getExtensionsHeader(dialect, variant, extensions): extensionsHeaderMutex.release() return extensionHeader - def getDialectAndVariantHeaders(dialect, variant, extensions=None): result = [] headerPath = args.source_dir + '/libraries/shaders/headers/' @@ -80,6 +79,14 @@ def getDialectAndVariantHeaders(dialect, variant, extensions=None): result.append(variantHeader) return result +def getDefines(defines): + definesList = [] + if defines: + definesSplit = defines.split("_") + for define in definesSplit: + definesList.append('HIFI_USE_{} 1'.format(define.upper())) + return definesList + class ScribeDependenciesCache: cache = {} lock = Lock() @@ -99,9 +106,9 @@ class ScribeDependenciesCache: with open(self.filename, "w") as f: f.write(json.dumps(self.cache)) - def get(self, scribefile, dialect, variant): + def get(self, scribefile, dialect, variant, defines): self.lock.acquire() - key = self.key(scribefile, dialect, variant) + key = self.key(scribefile, dialect, variant, defines) try: if key in self.cache: return self.cache[key].copy() @@ -109,25 +116,26 @@ class ScribeDependenciesCache: self.lock.release() return None - def key(self, scribeFile, dialect, variant): - return ':'.join([scribeFile, dialect, variant]) + def key(self, scribeFile, dialect, variant, defines): + return ':'.join([scribeFile, dialect, variant, defines]) - def getOrGen(self, scribefile, includeLibs, dialect, variant): - result = self.get(scribefile, dialect, variant) - if (None == result): - result = self.gen(scribefile, includeLibs, dialect, variant) + def getOrGen(self, scribefile, includeLibs, dialect, variant, defines): + result = self.get(scribefile, dialect, variant, defines) + if result is None: + result = self.gen(scribefile, includeLibs, dialect, variant, defines) return result - def gen(self, scribefile, includeLibs, dialect, variant): + def gen(self, scribefile, includeLibs, dialect, variant, defines): scribeArgs = getCommonScribeArgs(scribefile, includeLibs) scribeArgs.extend(['-M']) processResult = subprocess.run(scribeArgs, stdout=subprocess.PIPE) if (0 != processResult.returncode): - raise RuntimeError("Unable to parse scribe dependencies") + raise RuntimeError("Unable to parse scribe dependencies for file {} with defines: {}".format(scribefile, defines)) result = processResult.stdout.decode("utf-8").splitlines(False) result.append(scribefile) result.extend(getDialectAndVariantHeaders(dialect, variant)) - key = self.key(scribefile, dialect, variant) + result.extend(getDefines(defines)) + key = self.key(scribefile, dialect, variant, defines) self.lock.acquire() self.cache[key] = result.copy() self.lock.release() @@ -166,6 +174,10 @@ def processCommand(line): variant = params.pop(0) scribeFile = args.source_dir + '/' + params.pop(0) unoptGlslFile = args.source_dir + '/' + params.pop(0) + defines = "" + if len(params) > 1 and params[0].startswith("defines:"): + defines = params.pop(0) + defines = defines[len("defines:"):] libs = params upoptSpirvFile = unoptGlslFile + '.spv' @@ -184,19 +196,23 @@ def processCommand(line): os.makedirs(scribeOutputDir) folderMutex.release() - scribeDeps = scribeDepCache.getOrGen(scribeFile, libs, dialect, variant) + scribeDeps = scribeDepCache.getOrGen(scribeFile, libs, dialect, variant, defines) # if the scribe sources (slv, slf, slh, etc), or the dialect/ variant headers are out of date # regenerate the scribe GLSL output if args.force or outOfDate(scribeDeps, outputFiles): - print('Processing file {} dialect {} variant {}'.format(scribeFile, dialect, variant)) + print('Processing file {} dialect {} variant {} defines {}'.format(scribeFile, dialect, variant, defines)) if args.dry_run: return True - scribeDepCache.gen(scribeFile, libs, dialect, variant) + scribeDepCache.gen(scribeFile, libs, dialect, variant, defines) scribeArgs = getCommonScribeArgs(scribeFile, libs) for header in getDialectAndVariantHeaders(dialect, variant, args.extensions): scribeArgs.extend(['-H', header]) + for define in getDefines(defines): + defineArgs = ['-D'] + defineArgs.extend(define.split(' ')) + scribeArgs.extend(defineArgs) scribeArgs.extend(['-o', unoptGlslFile]) executeSubprocess(scribeArgs) From 476f0ed012eb171860275942507c8a3c0be8354c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 3 Jun 2019 20:45:46 -0700 Subject: [PATCH 02/77] cleanup and fixing some issues --- .../src/RenderableGridEntityItem.cpp | 2 +- libraries/entities-renderer/src/polyvox.slf | 2 +- libraries/render-utils/src/grid.slf | 15 +++++++-------- libraries/render-utils/src/model.slf | 10 +++++++++- libraries/render-utils/src/simple.slv | 11 ++++++++--- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index 31969e36fc..d8f0d93bb6 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -122,7 +122,7 @@ void GridEntityRenderer::doRender(RenderArgs* args) { forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD; }); - if (!_visible) { + if (!_visible || color.a == 0.0f) { return; } diff --git a/libraries/entities-renderer/src/polyvox.slf b/libraries/entities-renderer/src/polyvox.slf index b703a6868c..37cc7bcbbc 100644 --- a/libraries/entities-renderer/src/polyvox.slf +++ b/libraries/entities-renderer/src/polyvox.slf @@ -94,7 +94,7 @@ void main(void) { DEFAULT_METALLIC, DEFAULT_EMISSIVE <@if HIFI_USE_FADE@> - + fadeEmissive + + fadeEmissive <@endif@> , DEFAULT_OCCLUSION, diff --git a/libraries/render-utils/src/grid.slf b/libraries/render-utils/src/grid.slf index 68e6d019c0..f0a0741e5a 100644 --- a/libraries/render-utils/src/grid.slf +++ b/libraries/render-utils/src/grid.slf @@ -33,21 +33,20 @@ layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0; layout(location=GPU_ATTR_COLOR) in vec4 varColor; void main(void) { - float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge), + float gridLine = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge), paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy), float(grid.edge.z == 0.0)); + if (gridLine <= 0.0) { + discard; + } <@if not HIFI_USE_FORWARD@> <@if not HIFI_USE_TRANSLUCENT@> - packDeferredFragmentUnlit(vec3(1.0, 0.0, 0.0), alpha, varColor.rgb); + packDeferredFragmentUnlit(vec3(1.0, 0.0, 0.0), 1.0, varColor.rgb); <@else@> - packDeferredFragmentTranslucent(vec3(1.0, 0.0, 0.0), alpha, varColor.rgb, DEFAULT_ROUGHNESS); + packDeferredFragmentTranslucent(vec3(1.0, 0.0, 0.0), varColor.a, varColor.rgb, DEFAULT_ROUGHNESS); <@endif@> <@else@> - const float EPSILON = 0.0001; - if (alpha < EPSILON) { - discard; - } - _fragColor0 = vec4(varColor.rgb, alpha); + _fragColor0 = varColor; <@endif@> } diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index 7803974ec8..374248765d 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -104,7 +104,11 @@ void main(void) { <@if HIFI_USE_SHADOW or HIFI_USE_UNLIT@> <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> + <@if HIFI_USE_TRANSLUCENT@> + float opacity = getMaterialOpacity(mat) * _color.a; + <@else@> float opacity = 1.0; + <@endif@> <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <@if HIFI_USE_TRANSLUCENT@> <$discardInvisible(opacity)$>; @@ -152,7 +156,11 @@ void main(void) { <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> <@endif@> + <@if HIFI_USE_TRANSLUCENT@> + float opacity = getMaterialOpacity(mat) * _color.a; + <@else@> float opacity = 1.0; + <@endif@> <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <@if HIFI_USE_TRANSLUCENT@> <$discardInvisible(opacity)$>; @@ -301,7 +309,7 @@ void main(void) { metallic, emissive <@if HIFI_USE_FADE@> - + fadeEmissive + + fadeEmissive <@endif@> , surfaceWS, opacity, localLighting.rgb), diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index f766acceda..e47af5d23f 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -17,14 +17,18 @@ <@include render-utils/ShaderConstants.h@> +<@if HIFI_USE_FADE@> + <@include Fade.slh@> + <$declareFadeVertexInstanced()$> + + layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; +<@endif@> + <@if not HIFI_USE_UNLIT@> <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; <@endif@> <@endif@> -<@if HIFI_USE_FADE@> - layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -<@endif@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; @@ -47,6 +51,7 @@ void main(void) { <@if HIFI_USE_FADE@> <$transformModelToWorldPos(obj, inPosition, _positionWS)$> + <$passThroughFadeObjectParams()$> <@endif@> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> } \ No newline at end of file From fb4be671e75263b3fe19dafc3b1d44943383d764 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 26 Jun 2019 10:54:50 -0700 Subject: [PATCH 03/77] fix invoke call --- libraries/script-engine/src/ScriptEngines.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 17f2aea9a5..386b966589 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -461,7 +461,8 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i Q_ARG(bool, isUserLoaded), Q_ARG(bool, loadScriptFromEditor), Q_ARG(bool, activateMainWindow), - Q_ARG(bool, reload)); + Q_ARG(bool, reload), + Q_ARG(bool, quitWhenFinished)); return result; } QUrl scriptUrl; From 7573c1207b3e6128ea0839298ffdacca7623862c Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 26 Jun 2019 11:21:52 -0700 Subject: [PATCH 04/77] remove extra alpha check in deferred sdf_text3D.slf --- libraries/render-utils/src/sdf_text3D.slf | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index ab67447d04..a581bf4650 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -80,10 +80,6 @@ void main() { alpha); <@endif@> <@else@> - if (alpha <= 0.0) { - discard; - } - packDeferredFragment( normalize(_normalWS), alpha, @@ -94,4 +90,4 @@ void main() { DEFAULT_OCCLUSION, DEFAULT_SCATTERING); <@endif@> -} \ No newline at end of file +} From 692c776be50fd151c91831a9f7096b1b63a3f99a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 2 Jul 2019 15:18:28 -0700 Subject: [PATCH 05/77] expose shadow bias and max distance wip --- .../src/RenderableZoneEntityItem.cpp | 2 + .../entities/src/EntityItemProperties.cpp | 2 + libraries/entities/src/EntityPropertyFlags.h | 60 ++++++++++--------- .../entities/src/KeyLightPropertyGroup.cpp | 44 ++++++++++++-- .../entities/src/KeyLightPropertyGroup.h | 8 +++ libraries/networking/src/udt/PacketHeaders.h | 1 + .../system/assets/data/createAppTooltips.json | 8 ++- .../system/html/js/entityProperties.js | 20 +++++++ .../create/assets/data/createAppTooltips.json | 8 ++- .../html/js/entityProperties.js | 20 +++++++ 10 files changed, 139 insertions(+), 34 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index e4300cca76..266acf6188 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -317,6 +317,8 @@ void ZoneEntityRenderer::updateKeySunFromEntity(const TypedEntityPointer& entity sunLight->setIntensity(_keyLightProperties.getIntensity()); sunLight->setDirection(_lastRotation * _keyLightProperties.getDirection()); sunLight->setCastShadows(_keyLightProperties.getCastShadows()); + sunLight->setShadowsBiasScale(_keyLightProperties.getShadowBias()); + sunLight->setShadowsMaxDistance(_keyLightProperties.getShadowMaxDistance()); } void ZoneEntityRenderer::updateAmbientLightFromEntity(const TypedEntityPointer& entity) { diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 064fe2e3b1..6e0b843b8f 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -2746,6 +2746,8 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity); ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLight, keylight, Direction, direction); ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_CAST_SHADOW, KeyLight, keyLight, CastShadows, castShadows); + ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_BIAS, KeyLight, keyLight, ShadowBias, shadowBias, 0.0f, 1.0f); + ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, KeyLight, keyLight, ShadowMaxDistance, shadowMaxDistance, 0.0f, 500.0f); } { // Ambient light ADD_GROUP_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_INTENSITY, AmbientLight, ambientLight, Intensity, intensity); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index e86cccb997..b751dbfaec 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -159,6 +159,8 @@ enum EntityPropertyList { PROP_DERIVED_29, PROP_DERIVED_30, PROP_DERIVED_31, + PROP_DERIVED_32, + PROP_DERIVED_33, PROP_AFTER_LAST_ITEM, @@ -248,39 +250,41 @@ enum EntityPropertyList { PROP_KEYLIGHT_INTENSITY = PROP_DERIVED_1, PROP_KEYLIGHT_DIRECTION = PROP_DERIVED_2, PROP_KEYLIGHT_CAST_SHADOW = PROP_DERIVED_3, + PROP_KEYLIGHT_SHADOW_BIAS = PROP_DERIVED_4, + PROP_KEYLIGHT_SHADOW_MAX_DISTANCE = PROP_DERIVED_5, // Ambient light - PROP_AMBIENT_LIGHT_INTENSITY = PROP_DERIVED_4, - PROP_AMBIENT_LIGHT_URL = PROP_DERIVED_5, + PROP_AMBIENT_LIGHT_INTENSITY = PROP_DERIVED_6, + PROP_AMBIENT_LIGHT_URL = PROP_DERIVED_7, // Skybox - PROP_SKYBOX_COLOR = PROP_DERIVED_6, - PROP_SKYBOX_URL = PROP_DERIVED_7, + PROP_SKYBOX_COLOR = PROP_DERIVED_8, + PROP_SKYBOX_URL = PROP_DERIVED_9, // Haze - PROP_HAZE_RANGE = PROP_DERIVED_8, - PROP_HAZE_COLOR = PROP_DERIVED_9, - PROP_HAZE_GLARE_COLOR = PROP_DERIVED_10, - PROP_HAZE_ENABLE_GLARE = PROP_DERIVED_11, - PROP_HAZE_GLARE_ANGLE = PROP_DERIVED_12, - PROP_HAZE_ALTITUDE_EFFECT = PROP_DERIVED_13, - PROP_HAZE_CEILING = PROP_DERIVED_14, - PROP_HAZE_BASE_REF = PROP_DERIVED_15, - PROP_HAZE_BACKGROUND_BLEND = PROP_DERIVED_16, - PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_DERIVED_17, - PROP_HAZE_KEYLIGHT_RANGE = PROP_DERIVED_18, - PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_DERIVED_19, + PROP_HAZE_RANGE = PROP_DERIVED_10, + PROP_HAZE_COLOR = PROP_DERIVED_11, + PROP_HAZE_GLARE_COLOR = PROP_DERIVED_12, + PROP_HAZE_ENABLE_GLARE = PROP_DERIVED_13, + PROP_HAZE_GLARE_ANGLE = PROP_DERIVED_14, + PROP_HAZE_ALTITUDE_EFFECT = PROP_DERIVED_15, + PROP_HAZE_CEILING = PROP_DERIVED_16, + PROP_HAZE_BASE_REF = PROP_DERIVED_17, + PROP_HAZE_BACKGROUND_BLEND = PROP_DERIVED_18, + PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_DERIVED_19, + PROP_HAZE_KEYLIGHT_RANGE = PROP_DERIVED_20, + PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_DERIVED_21, // Bloom - PROP_BLOOM_INTENSITY = PROP_DERIVED_20, - PROP_BLOOM_THRESHOLD = PROP_DERIVED_21, - PROP_BLOOM_SIZE = PROP_DERIVED_22, - PROP_FLYING_ALLOWED = PROP_DERIVED_23, - PROP_GHOSTING_ALLOWED = PROP_DERIVED_24, - PROP_FILTER_URL = PROP_DERIVED_25, - PROP_KEY_LIGHT_MODE = PROP_DERIVED_26, - PROP_AMBIENT_LIGHT_MODE = PROP_DERIVED_27, - PROP_SKYBOX_MODE = PROP_DERIVED_28, - PROP_HAZE_MODE = PROP_DERIVED_29, - PROP_BLOOM_MODE = PROP_DERIVED_30, + PROP_BLOOM_INTENSITY = PROP_DERIVED_22, + PROP_BLOOM_THRESHOLD = PROP_DERIVED_23, + PROP_BLOOM_SIZE = PROP_DERIVED_24, + PROP_FLYING_ALLOWED = PROP_DERIVED_25, + PROP_GHOSTING_ALLOWED = PROP_DERIVED_26, + PROP_FILTER_URL = PROP_DERIVED_27, + PROP_KEY_LIGHT_MODE = PROP_DERIVED_28, + PROP_AMBIENT_LIGHT_MODE = PROP_DERIVED_29, + PROP_SKYBOX_MODE = PROP_DERIVED_30, + PROP_HAZE_MODE = PROP_DERIVED_31, + PROP_BLOOM_MODE = PROP_DERIVED_32, // Avatar priority - PROP_AVATAR_PRIORITY = PROP_DERIVED_31, + PROP_AVATAR_PRIORITY = PROP_DERIVED_33, // Polyvox PROP_VOXEL_VOLUME_SIZE = PROP_DERIVED_0, diff --git a/libraries/entities/src/KeyLightPropertyGroup.cpp b/libraries/entities/src/KeyLightPropertyGroup.cpp index f0ad2965ce..b70e94504d 100644 --- a/libraries/entities/src/KeyLightPropertyGroup.cpp +++ b/libraries/entities/src/KeyLightPropertyGroup.cpp @@ -22,6 +22,8 @@ const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_INTENSITY = 1.0f; const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY = 0.5f; const glm::vec3 KeyLightPropertyGroup::DEFAULT_KEYLIGHT_DIRECTION = { 0.0f, -1.0f, 0.0f }; const bool KeyLightPropertyGroup::DEFAULT_KEYLIGHT_CAST_SHADOWS { false }; +const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_SHADOW_BIAS { 0.5f }; +const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_SHADOW_MAX_DISTANCE { 40.0f }; void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { @@ -30,6 +32,8 @@ void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desired COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_DIRECTION, KeyLight, keyLight, Direction, direction); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_CAST_SHADOW, KeyLight, keyLight, CastShadows, castShadows); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_SHADOW_BIAS, KeyLight, keyLight, ShadowBias, shadowBias); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, KeyLight, keyLight, ShadowMaxDistance, shadowMaxDistance); } void KeyLightPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) { @@ -37,6 +41,8 @@ void KeyLightPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, intensity, float, setIntensity); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, direction, vec3, setDirection); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, castShadows, bool, setCastShadows); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, shadowBias, float, setShadowBias); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, shadowMaxDistance, float, setShadowMaxDistance); // legacy property support COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightColor, u8vec3Color, setColor, getColor); @@ -50,14 +56,18 @@ void KeyLightPropertyGroup::merge(const KeyLightPropertyGroup& other) { COPY_PROPERTY_IF_CHANGED(intensity); COPY_PROPERTY_IF_CHANGED(direction); COPY_PROPERTY_IF_CHANGED(castShadows); + COPY_PROPERTY_IF_CHANGED(shadowBias); + COPY_PROPERTY_IF_CHANGED(shadowMaxDistance); } void KeyLightPropertyGroup::debugDump() const { qCDebug(entities) << " KeyLightPropertyGroup: ---------------------------------------------"; - qCDebug(entities) << " color:" << getColor(); // << "," << getColor()[1] << "," << getColor()[2]; - qCDebug(entities) << " intensity:" << getIntensity(); - qCDebug(entities) << " direction:" << getDirection(); - qCDebug(entities) << " castShadows:" << getCastShadows(); + qCDebug(entities) << " color:" << getColor(); + qCDebug(entities) << " intensity:" << getIntensity(); + qCDebug(entities) << " direction:" << getDirection(); + qCDebug(entities) << " castShadows:" << getCastShadows(); + qCDebug(entities) << " shadowBias:" << getShadowBias(); + qCDebug(entities) << " shadowMaxDistance:" << getShadowMaxDistance(); } void KeyLightPropertyGroup::listChangedProperties(QList& out) { @@ -73,6 +83,12 @@ void KeyLightPropertyGroup::listChangedProperties(QList& out) { if (castShadowsChanged()) { out << "keyLight-castShadows"; } + if (shadowBiasChanged()) { + out << "keyLight-shadowBias"; + } + if (shadowMaxDistanceChanged()) { + out << "keyLight-shadowMaxDistance"; + } } bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData, @@ -88,6 +104,8 @@ bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, getCastShadows()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, getShadowBias()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, getShadowMaxDistance()); return true; } @@ -103,11 +121,15 @@ bool KeyLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFl READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, bool, setCastShadows); + READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, float, setShadowBias); + READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, float, setShadowMaxDistance); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_COLOR, Color); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_INTENSITY, Intensity); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_DIRECTION, Direction); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_CAST_SHADOW, CastShadows); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_SHADOW_BIAS, ShadowBias); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, ShadowMaxDistance); processedBytes += bytesRead; @@ -121,6 +143,8 @@ void KeyLightPropertyGroup::markAllChanged() { _intensityChanged = true; _directionChanged = true; _castShadowsChanged = true; + _shadowBiasChanged = true; + _shadowMaxDistanceChanged = true; } EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const { @@ -130,6 +154,8 @@ EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_INTENSITY, intensity); CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_DIRECTION, direction); CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_CAST_SHADOW, castShadows); + CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_SHADOW_BIAS, shadowBias); + CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, shadowMaxDistance); return changedProperties; } @@ -139,6 +165,8 @@ void KeyLightPropertyGroup::getProperties(EntityItemProperties& properties) cons COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Intensity, getIntensity); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Direction, getDirection); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, CastShadows, getCastShadows); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, ShadowBias, getShadowBias); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, ShadowMaxDistance, getShadowMaxDistance); } bool KeyLightPropertyGroup::setProperties(const EntityItemProperties& properties) { @@ -148,6 +176,8 @@ bool KeyLightPropertyGroup::setProperties(const EntityItemProperties& properties SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Intensity, intensity, setIntensity); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Direction, direction, setDirection); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, CastShadows, castShadows, setCastShadows); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, ShadowBias, shadowBias, setShadowBias); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, ShadowMaxDistance, shadowMaxDistance, setShadowMaxDistance); return somethingChanged; } @@ -159,6 +189,8 @@ EntityPropertyFlags KeyLightPropertyGroup::getEntityProperties(EncodeBitstreamPa requestedProperties += PROP_KEYLIGHT_INTENSITY; requestedProperties += PROP_KEYLIGHT_DIRECTION; requestedProperties += PROP_KEYLIGHT_CAST_SHADOW; + requestedProperties += PROP_KEYLIGHT_SHADOW_BIAS; + requestedProperties += PROP_KEYLIGHT_SHADOW_MAX_DISTANCE; return requestedProperties; } @@ -177,6 +209,8 @@ void KeyLightPropertyGroup::appendSubclassData(OctreePacketData* packetData, Enc APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, getCastShadows()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, getShadowBias()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, getShadowMaxDistance()); } int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -191,6 +225,8 @@ int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, bool, setCastShadows); + READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, float, setShadowBias); + READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, float, setShadowMaxDistance); return bytesRead; } diff --git a/libraries/entities/src/KeyLightPropertyGroup.h b/libraries/entities/src/KeyLightPropertyGroup.h index d46f5ce9b5..15e83ba5b1 100644 --- a/libraries/entities/src/KeyLightPropertyGroup.h +++ b/libraries/entities/src/KeyLightPropertyGroup.h @@ -37,6 +37,10 @@ class ReadBitstreamToTreeParams; * are cast by avatars, plus {@link Entities.EntityProperties-Model|Model} and * {@link Entities.EntityProperties-Shape|Shape} entities that have their * {@link Entities.EntityProperties|canCastShadow} property set to true. + * @property {number} shadowBias=0.5 - The bias of the shadows cast by the light. Use this to fine-tune your shadows to your scene + * to prevent shadow acne and peter panning. In the range 0.01.0. + * @property {number} shadowMaxDistance=40.0 - The max distance from your view at which shadows will be computed. Higher values will + * cover more of your scene, but with less precision. In the range 0.0500.0. */ class KeyLightPropertyGroup : public PropertyGroup { public: @@ -90,11 +94,15 @@ public: static const float DEFAULT_KEYLIGHT_AMBIENT_INTENSITY; static const glm::vec3 DEFAULT_KEYLIGHT_DIRECTION; static const bool DEFAULT_KEYLIGHT_CAST_SHADOWS; + static const float DEFAULT_KEYLIGHT_SHADOW_BIAS; + static const float DEFAULT_KEYLIGHT_SHADOW_MAX_DISTANCE; DEFINE_PROPERTY_REF(PROP_KEYLIGHT_COLOR, Color, color, glm::u8vec3, DEFAULT_KEYLIGHT_COLOR); DEFINE_PROPERTY(PROP_KEYLIGHT_INTENSITY, Intensity, intensity, float, DEFAULT_KEYLIGHT_INTENSITY); DEFINE_PROPERTY_REF(PROP_KEYLIGHT_DIRECTION, Direction, direction, glm::vec3, DEFAULT_KEYLIGHT_DIRECTION); DEFINE_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, CastShadows, castShadows, bool, DEFAULT_KEYLIGHT_CAST_SHADOWS); + DEFINE_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, ShadowBias, shadowBias, float, DEFAULT_KEYLIGHT_SHADOW_BIAS); + DEFINE_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, ShadowMaxDistance, shadowMaxDistance, float, DEFAULT_KEYLIGHT_SHADOW_MAX_DISTANCE); }; #endif // hifi_KeyLightPropertyGroup_h diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 6230b8b11e..9e4f7cf808 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -271,6 +271,7 @@ enum class EntityVersion : PacketVersion { ParticleShapeType, ParticleShapeTypeDeadlockFix, PrivateUserData, + ShadowBiasAndDistance, // Add new versions above here NUM_PACKET_TYPE, diff --git a/scripts/simplifiedUI/system/assets/data/createAppTooltips.json b/scripts/simplifiedUI/system/assets/data/createAppTooltips.json index b59797fca7..f22552b462 100644 --- a/scripts/simplifiedUI/system/assets/data/createAppTooltips.json +++ b/scripts/simplifiedUI/system/assets/data/createAppTooltips.json @@ -74,6 +74,12 @@ "keyLight.castShadows": { "tooltip": "If enabled, shadows are cast. The entity or avatar casting the shadow must also have Cast Shadows enabled." }, + "keyLight.shadowBias": { + "tooltip": "The bias of the shadows cast by the light. Use this to fine-tune your shadows to your scene to prevent shadow acne and peter panning." + }, + "keyLight.shadowMaxDistance": { + "tooltip": "The max distance from your view at which shadows will be computed." + }, "skyboxMode": { "tooltip": "Configures the skybox in the zone. The skybox is a cube map image." }, @@ -135,7 +141,7 @@ "tooltip": "The radius of bloom. The higher the value, the larger the bloom." }, "avatarPriority": { - "tooltip": "Alter Avatars' update priorities." + "tooltip": "Alter Avatars' update priorities." }, "modelURL": { "tooltip": "A mesh model from an FBX or OBJ file." diff --git a/scripts/simplifiedUI/system/html/js/entityProperties.js b/scripts/simplifiedUI/system/html/js/entityProperties.js index e64543d41f..c04d42c606 100644 --- a/scripts/simplifiedUI/system/html/js/entityProperties.js +++ b/scripts/simplifiedUI/system/html/js/entityProperties.js @@ -300,6 +300,26 @@ const GROUPS = [ propertyID: "keyLight.castShadows", showPropertyRule: { "keyLightMode": "enabled" }, }, + { + label: "Shadow Bias", + type: "number-draggable", + min: 0, + max: 1, + step: 0.01, + decimals: 2, + propertyID: "keyLight.shadowBias", + showPropertyRule: { "keyLightMode": "enabled" }, + }, + { + label: "Shadow Max Distance", + type: "number-draggable", + min: 0, + max: 500, + step: 0.1, + decimals: 2, + propertyID: "keyLight.shadowMaxDistance", + showPropertyRule: { "keyLightMode": "enabled" }, + }, { label: "Skybox", type: "dropdown", diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index b59797fca7..f22552b462 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -74,6 +74,12 @@ "keyLight.castShadows": { "tooltip": "If enabled, shadows are cast. The entity or avatar casting the shadow must also have Cast Shadows enabled." }, + "keyLight.shadowBias": { + "tooltip": "The bias of the shadows cast by the light. Use this to fine-tune your shadows to your scene to prevent shadow acne and peter panning." + }, + "keyLight.shadowMaxDistance": { + "tooltip": "The max distance from your view at which shadows will be computed." + }, "skyboxMode": { "tooltip": "Configures the skybox in the zone. The skybox is a cube map image." }, @@ -135,7 +141,7 @@ "tooltip": "The radius of bloom. The higher the value, the larger the bloom." }, "avatarPriority": { - "tooltip": "Alter Avatars' update priorities." + "tooltip": "Alter Avatars' update priorities." }, "modelURL": { "tooltip": "A mesh model from an FBX or OBJ file." diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index e64543d41f..c04d42c606 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -300,6 +300,26 @@ const GROUPS = [ propertyID: "keyLight.castShadows", showPropertyRule: { "keyLightMode": "enabled" }, }, + { + label: "Shadow Bias", + type: "number-draggable", + min: 0, + max: 1, + step: 0.01, + decimals: 2, + propertyID: "keyLight.shadowBias", + showPropertyRule: { "keyLightMode": "enabled" }, + }, + { + label: "Shadow Max Distance", + type: "number-draggable", + min: 0, + max: 500, + step: 0.1, + decimals: 2, + propertyID: "keyLight.shadowMaxDistance", + showPropertyRule: { "keyLightMode": "enabled" }, + }, { label: "Skybox", type: "dropdown", From c7442e3a62a64758806d24242da94f6e8874c313 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 2 Jul 2019 13:24:48 -0700 Subject: [PATCH 06/77] Remove QT_CMAKE_PREFIX_PATH prod hack --- cmake/macros/SetupQt.cmake | 10 ++-------- hifi_vcpkg.py | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/cmake/macros/SetupQt.cmake b/cmake/macros/SetupQt.cmake index 3ef0f9cde8..c09c2b0f6b 100644 --- a/cmake/macros/SetupQt.cmake +++ b/cmake/macros/SetupQt.cmake @@ -52,14 +52,8 @@ macro(setup_qt) message(FATAL_ERROR "VCPKG_QT_CMAKE_PREFIX_PATH should have been set by hifi_vcpkg.py") endif() if (NOT DEV_BUILD) - if (UNIX AND DEFINED ENV{QT_CMAKE_PREFIX_PATH} AND NOT APPLE) - # HACK: obey QT_CMAKE_PREFIX_PATH to allow UNIX to use older QT libs - message("HACK: obey QT_CMAKE_PREFIX_PATH on UNIX") - set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH}) - else() - message("override QT_CMAKE_PREFIX_PATH with VCPKG_QT_CMAKE_PREFIX_PATH") - set(QT_CMAKE_PREFIX_PATH ${VCPKG_QT_CMAKE_PREFIX_PATH}) - endif() + message("override QT_CMAKE_PREFIX_PATH with VCPKG_QT_CMAKE_PREFIX_PATH") + set(QT_CMAKE_PREFIX_PATH ${VCPKG_QT_CMAKE_PREFIX_PATH}) else() # DEV_BUILD if (DEFINED ENV{QT_CMAKE_PREFIX_PATH}) diff --git a/hifi_vcpkg.py b/hifi_vcpkg.py index 686ccfcfc7..764a6270bd 100644 --- a/hifi_vcpkg.py +++ b/hifi_vcpkg.py @@ -259,7 +259,7 @@ endif() url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos3.tar.gz' elif platform.system() == 'Linux': if platform.linux_distribution()[1][:3] == '16.': - url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04.tar.gz' + url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04-with-symbols.tar.gz' elif platform.linux_distribution()[1][:3] == '18.': url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-18.04.tar.gz' else: From 72f52b069e6e6b70dd84fb7b3366cc01c87c2cf8 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 3 Jul 2019 16:21:47 -0700 Subject: [PATCH 07/77] cleanup, fix shadow qml --- .../src/RenderableZoneEntityItem.cpp | 2 +- .../entities/src/EntityItemProperties.cpp | 2 +- .../entities/src/KeyLightPropertyGroup.h | 2 +- libraries/graphics/src/graphics/Light.cpp | 16 +-- libraries/graphics/src/graphics/Light.h | 12 +- .../render-utils/src/RenderShadowTask.cpp | 123 +++++++----------- libraries/render-utils/src/RenderShadowTask.h | 78 +++++------ scripts/developer/utilities/render/shadow.qml | 16 +-- .../system/html/js/entityProperties.js | 2 +- .../html/js/entityProperties.js | 2 +- 10 files changed, 101 insertions(+), 154 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 266acf6188..bbb8c67ad1 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -317,7 +317,7 @@ void ZoneEntityRenderer::updateKeySunFromEntity(const TypedEntityPointer& entity sunLight->setIntensity(_keyLightProperties.getIntensity()); sunLight->setDirection(_lastRotation * _keyLightProperties.getDirection()); sunLight->setCastShadows(_keyLightProperties.getCastShadows()); - sunLight->setShadowsBiasScale(_keyLightProperties.getShadowBias()); + sunLight->setShadowBias(_keyLightProperties.getShadowBias()); sunLight->setShadowsMaxDistance(_keyLightProperties.getShadowMaxDistance()); } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 019556b7f0..980cd31652 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -2754,7 +2754,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLight, keylight, Direction, direction); ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_CAST_SHADOW, KeyLight, keyLight, CastShadows, castShadows); ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_BIAS, KeyLight, keyLight, ShadowBias, shadowBias, 0.0f, 1.0f); - ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, KeyLight, keyLight, ShadowMaxDistance, shadowMaxDistance, 0.0f, 500.0f); + ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, KeyLight, keyLight, ShadowMaxDistance, shadowMaxDistance, 1.0f, 250.0f); } { // Ambient light ADD_GROUP_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_INTENSITY, AmbientLight, ambientLight, Intensity, intensity); diff --git a/libraries/entities/src/KeyLightPropertyGroup.h b/libraries/entities/src/KeyLightPropertyGroup.h index 15e83ba5b1..facbf88f3c 100644 --- a/libraries/entities/src/KeyLightPropertyGroup.h +++ b/libraries/entities/src/KeyLightPropertyGroup.h @@ -40,7 +40,7 @@ class ReadBitstreamToTreeParams; * @property {number} shadowBias=0.5 - The bias of the shadows cast by the light. Use this to fine-tune your shadows to your scene * to prevent shadow acne and peter panning. In the range 0.01.0. * @property {number} shadowMaxDistance=40.0 - The max distance from your view at which shadows will be computed. Higher values will - * cover more of your scene, but with less precision. In the range 0.0500.0. + * cover more of your scene, but with less precision. In the range 1.0250.0. */ class KeyLightPropertyGroup : public PropertyGroup { public: diff --git a/libraries/graphics/src/graphics/Light.cpp b/libraries/graphics/src/graphics/Light.cpp index a5d03beda1..fb14783b4e 100755 --- a/libraries/graphics/src/graphics/Light.cpp +++ b/libraries/graphics/src/graphics/Light.cpp @@ -81,20 +81,12 @@ float Light::getShadowsMaxDistance() const { return _shadowsMaxDistance; } -void Light::setShadowsBiasScale(const float scale) { - _shadowsBiasScale = std::max(0.0f, scale); +void Light::setShadowBias(float bias) { + _shadowBias = bias; } -float Light::getShadowsBiasScale() const { - return _shadowsBiasScale; -} - -void Light::setBiasInput(float bias) { - _biasInput = bias; -} - -float Light::getBiasInput() const { - return _biasInput; +float Light::getShadowBias() const { + return _shadowBias; } void Light::setColor(const Color& color) { diff --git a/libraries/graphics/src/graphics/Light.h b/libraries/graphics/src/graphics/Light.h index 9b431b3e26..37670176cc 100755 --- a/libraries/graphics/src/graphics/Light.h +++ b/libraries/graphics/src/graphics/Light.h @@ -109,11 +109,8 @@ public: void setShadowsMaxDistance(const float maxDistance); float getShadowsMaxDistance() const; - void setShadowsBiasScale(const float scale); - float getShadowsBiasScale() const; - - void setBiasInput(float bias); - float getBiasInput() const; + void setShadowBias(float bias); + float getShadowBias() const; void setOrientation(const Quat& orientation); const glm::quat& getOrientation() const { return _transform.getRotation(); } @@ -201,9 +198,8 @@ protected: Type _type { SUN }; float _spotCos { -1.0f }; // stored here to be able to reset the spot angle when turning the type spot on/off - float _shadowsMaxDistance{ 40.0f }; - float _shadowsBiasScale{ 1.0f }; - float _biasInput{ 0.5f }; // 0.23f will roughly give the default constant and slope values + float _shadowsMaxDistance { 40.0f }; + float _shadowBias { 0.5f }; // 0.23f will roughly give the default constant and slope values bool _castShadows{ false }; void updateLightRadius(); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index f54b2e563e..802dc633bf 100755 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -33,7 +33,6 @@ // but are readjusted afterwards #define SHADOW_FRUSTUM_NEAR 1.0f #define SHADOW_FRUSTUM_FAR 500.0f -static const unsigned int SHADOW_CASCADE_COUNT{ 4 }; using namespace render; @@ -316,76 +315,42 @@ RenderShadowSetup::RenderShadowSetup() : _shadowFrameCache = std::make_shared(); } -void RenderShadowSetup::configure(const Config& configuration) { - distanceTriggeredByConfig = _globalMaxDistance != configuration.globalMaxDistance; - biasTriggeredByConfig = _biasInput != configuration.biasInput; - - // go back to using the config's default bias values if a change to any of those is triggered - if (constant0 != configuration.constantBias0 || slope0 != configuration.slopeBias0 || - constant1 != configuration.constantBias1 || slope1 != configuration.slopeBias1 || - constant2 != configuration.constantBias2 || slope2 != configuration.slopeBias2 || - constant3 != configuration.constantBias3 || slope3 != configuration.slopeBias3) { - constant0 = configuration.constantBias0; - slope0 = configuration.slopeBias0; - constant1 = configuration.constantBias1; - slope1 = configuration.slopeBias1; - constant2 = configuration.constantBias2; - slope2 = configuration.slopeBias2; - constant3 = configuration.constantBias3; - slope3 = configuration.slopeBias3; - changeInDefaultConfigValues = true; - distanceTriggeredByConfig = false; - biasTriggeredByConfig = false; - - setConstantBias(0, constant0); - setSlopeBias(0, slope0); - - #if SHADOW_CASCADE_MAX_COUNT > 1 - setConstantBias(1, constant1); - setConstantBias(2, constant2); - setConstantBias(3, constant3); - - setSlopeBias(1, slope1); - setSlopeBias(2, slope2); - setSlopeBias(3, slope3); - #endif - } - - // modify bias using single input and work in calculateBias() - if (distanceTriggeredByConfig) { - changeInDefaultConfigValues = false; - _globalMaxDistance = configuration.globalMaxDistance; - calculateBiases(); - } - if (biasTriggeredByConfig) { - changeInDefaultConfigValues = false; - _biasInput = configuration.biasInput; - calculateBiases(); - } +void RenderShadowSetup::configure(const Config& config) { + constantBias0 = config.constantBias0; + constantBias1 = config.constantBias1; + constantBias2 = config.constantBias2; + constantBias3 = config.constantBias3; + slopeBias0 = config.slopeBias0; + slopeBias1 = config.slopeBias1; + slopeBias2 = config.slopeBias2; + slopeBias3 = config.slopeBias3; + biasInput = config.biasInput; + maxDistance = config.maxDistance; } -void RenderShadowSetup::calculateBiases() { +void RenderShadowSetup::calculateBiases(float biasInput) { // slope scaling values derived from ratio between original constantBias and slopeBias pairs - const std::array SLOPE_SCALES = {{ 2.7f, 3.0f, 3.7f, 3.5f }}; + const std::array SLOPE_SCALES = {{ 2.7f, 3.0f, 3.7f, 3.5f }}; const float CONVERT_BIAS = 100.0f; const float MIN_SCALE_DIVISOR = 0.5f; // the bias is relative to resolution // to remain consistent with the constant and slope bias values, the biasInput // value is in the 0.0 - 1.0 range but needs to be scaled up for further calculations + // TODO: expose variable resolution + int resolution = LightStage::Shadow::MAP_SIZE; + const int DEFAULT_RESOLUTION = LightStage::Shadow::MAP_SIZE; float inverseResolution = 1.0f / (float)resolution; int resolutionScale = DEFAULT_RESOLUTION * inverseResolution; - float convertedBias = _biasInput * (CONVERT_BIAS / resolutionScale); - std::array localConstants; - std::array localSlopes; + float convertedBias = biasInput * (CONVERT_BIAS / resolutionScale); float scaleFactor = 1.0f; for (int i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) { - scaleFactor = convertedBias * (cacasdeDistances[0] / glm::max(MIN_SCALE_DIVISOR, cacasdeDistances[i + 4])) * inverseResolution; - localConstants[i] = cacasdeDistances[i] * scaleFactor; - localSlopes[i] = cacasdeDistances[i] * scaleFactor * SLOPE_SCALES[i]; - setConstantBias(i, localConstants[i]); - setSlopeBias(i, localSlopes[i]); + scaleFactor = convertedBias * (cacasdeDistances[0] / glm::max(MIN_SCALE_DIVISOR, cacasdeDistances[i + SHADOW_CASCADE_MAX_COUNT])) * inverseResolution; + float constantBias = cacasdeDistances[i] * scaleFactor; + float slopeBias = cacasdeDistances[i] * scaleFactor * SLOPE_SCALES[i]; + setConstantBias(i, constantBias); + setSlopeBias(i, slopeBias); } } @@ -425,43 +390,47 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c output.edit2() = _cameraFrustum; if (!_globalShadowObject) { - _globalShadowObject = std::make_shared(currentKeyLight, SHADOW_CASCADE_COUNT); + _globalShadowObject = std::make_shared(currentKeyLight, SHADOW_CASCADE_MAX_COUNT); } - resolution = _globalShadowObject->MAP_SIZE; _globalShadowObject->setLight(currentKeyLight); _globalShadowObject->setKeylightFrustum(args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); - // if the max distance isn't altered externally, grab the value from the light - if (!distanceTriggeredByConfig && !biasTriggeredByConfig) { - _globalMaxDistance = currentKeyLight->getShadowsMaxDistance(); - } - _globalShadowObject->setMaxDistance(_globalMaxDistance); - - auto& firstCascade = _globalShadowObject->getCascade(0); - auto& firstCascadeFrustum = firstCascade.getFrustum(); - unsigned int cascadeIndex; - for (cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { + // Update our biases and maxDistance from the light or config + _globalShadowObject->setMaxDistance(maxDistance > 0.0f ? maxDistance : currentKeyLight->getShadowsMaxDistance()); + + for (unsigned int cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { cacasdeDistances[cascadeIndex] = _globalShadowObject->getCascade(cascadeIndex).getMaxDistance(); - cacasdeDistances[cascadeIndex + 4] = _globalShadowObject->getCascade(cascadeIndex).getMinDistance(); + cacasdeDistances[cascadeIndex + SHADOW_CASCADE_MAX_COUNT] = _globalShadowObject->getCascade(cascadeIndex).getMinDistance(); } - if (!biasTriggeredByConfig && !distanceTriggeredByConfig && !changeInDefaultConfigValues) { - setBiasInput(currentKeyLight->getBiasInput()); - calculateBiases(); + calculateBiases(biasInput > 0.0f ? biasInput : currentKeyLight->getShadowBias()); + + std::array constantBiases = { constantBias0, constantBias1, constantBias2, constantBias3 }; + std::array slopeBiases = { slopeBias0, slopeBias1, slopeBias2, slopeBias3 }; + for (unsigned int cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { + float constantBias = constantBiases[cascadeIndex]; + if (constantBias > 0.0f) { + setConstantBias(cascadeIndex, constantBias); + } + float slopeBias = slopeBiases[cascadeIndex]; + if (slopeBias > 0.0f) { + setSlopeBias(cascadeIndex, slopeBias); + } } // Adjust each cascade frustum - const auto biasScale = currentKeyLight->getShadowsBiasScale(); - for (cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { + for (unsigned int cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { auto& bias = _bias[cascadeIndex]; _globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR, - bias._constant, bias._slope * biasScale); + bias._constant, bias._slope); } _shadowFrameCache->pushShadow(_globalShadowObject); // Now adjust coarse frustum bounds + auto& firstCascade = _globalShadowObject->getCascade(0); + auto& firstCascadeFrustum = firstCascade.getFrustum(); auto frustumPosition = firstCascadeFrustum->getPosition(); auto farTopLeft = firstCascadeFrustum->getFarTopLeft() - frustumPosition; auto farBottomRight = firstCascadeFrustum->getFarBottomRight() - frustumPosition; @@ -473,7 +442,7 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c auto near = firstCascadeFrustum->getNearClip(); auto far = firstCascadeFrustum->getFarClip(); - for (cascadeIndex = 1; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { + for (unsigned int cascadeIndex = 1; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { auto& cascadeFrustum = _globalShadowObject->getCascade(cascadeIndex).getFrustum(); farTopLeft = cascadeFrustum->getFarTopLeft() - frustumPosition; diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index ceca28cec8..23047ee179 100755 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -75,34 +75,31 @@ public: CullFunctor _cullFunctor; }; -const float DEFAULT_BIAS_INPUT = 0.5f; -const float DEFAULT_MAX_DISTANCE = 40.0f; - class RenderShadowSetupConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(float constantBias0 MEMBER constantBias0 NOTIFY dirty) - Q_PROPERTY(float constantBias1 MEMBER constantBias1 NOTIFY dirty) - Q_PROPERTY(float constantBias2 MEMBER constantBias2 NOTIFY dirty) - Q_PROPERTY(float constantBias3 MEMBER constantBias3 NOTIFY dirty) - Q_PROPERTY(float slopeBias0 MEMBER slopeBias0 NOTIFY dirty) - Q_PROPERTY(float slopeBias1 MEMBER slopeBias1 NOTIFY dirty) - Q_PROPERTY(float slopeBias2 MEMBER slopeBias2 NOTIFY dirty) - Q_PROPERTY(float slopeBias3 MEMBER slopeBias3 NOTIFY dirty) - Q_PROPERTY(float biasInput MEMBER biasInput NOTIFY dirty) - Q_PROPERTY(float globalMaxDistance MEMBER globalMaxDistance NOTIFY dirty) + Q_PROPERTY(float constantBias0 MEMBER constantBias0 NOTIFY dirty) + Q_PROPERTY(float constantBias1 MEMBER constantBias1 NOTIFY dirty) + Q_PROPERTY(float constantBias2 MEMBER constantBias2 NOTIFY dirty) + Q_PROPERTY(float constantBias3 MEMBER constantBias3 NOTIFY dirty) + Q_PROPERTY(float slopeBias0 MEMBER slopeBias0 NOTIFY dirty) + Q_PROPERTY(float slopeBias1 MEMBER slopeBias1 NOTIFY dirty) + Q_PROPERTY(float slopeBias2 MEMBER slopeBias2 NOTIFY dirty) + Q_PROPERTY(float slopeBias3 MEMBER slopeBias3 NOTIFY dirty) + Q_PROPERTY(float biasInput MEMBER biasInput NOTIFY dirty) + Q_PROPERTY(float maxDistance MEMBER maxDistance NOTIFY dirty) public: - float biasInput{ DEFAULT_BIAS_INPUT }; - float globalMaxDistance{ DEFAULT_MAX_DISTANCE }; - - float constantBias0{ 0.15f }; - float constantBias1{ 0.15f }; - float constantBias2{ 0.175f }; - float constantBias3{ 0.2f }; - float slopeBias0{ 0.4f }; - float slopeBias1{ 0.45f }; - float slopeBias2{ 0.65f }; - float slopeBias3{ 0.7f }; + // Set to > 0 to experiment with these values + float constantBias0 { 0.0f }; + float constantBias1 { 0.0f }; + float constantBias2 { 0.0f }; + float constantBias3 { 0.0f }; + float slopeBias0 { 0.0f }; + float slopeBias1 { 0.0f }; + float slopeBias2 { 0.0f }; + float slopeBias3 { 0.0f }; + float biasInput { 0.0f }; + float maxDistance { 0.0f }; signals: void dirty(); @@ -116,7 +113,7 @@ public: using JobModel = render::Job::ModelIO; RenderShadowSetup(); - void configure(const Config& configuration); + void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); private: @@ -130,29 +127,22 @@ private: LightStage::ShadowFrame::Object _globalShadowObject; LightStage::ShadowFramePointer _shadowFrameCache; - const int DEFAULT_RESOLUTION = 1024; - float _biasInput{ DEFAULT_BIAS_INPUT }; - float _globalMaxDistance{ DEFAULT_MAX_DISTANCE }; - int resolution{ DEFAULT_RESOLUTION }; - - // initialize with values from RenderShadowSetupConfig - float constant0{ 0.15f }; - float constant1{ 0.15f }; - float constant2{ 0.175f }; - float constant3{ 0.2f }; - float slope0{ 0.4f }; - float slope1{ 0.45f }; - float slope2{ 0.65f }; - float slope3{ 0.7f }; - bool changeInDefaultConfigValues{ false }; - bool distanceTriggeredByConfig{ false }; - bool biasTriggeredByConfig{ false }; + // Values from config + float constantBias0; + float constantBias1; + float constantBias2; + float constantBias3; + float slopeBias0; + float slopeBias1; + float slopeBias2; + float slopeBias3; + float biasInput; + float maxDistance; std::array cacasdeDistances; // 4 max then 4 min distances void setConstantBias(int cascadeIndex, float value); void setSlopeBias(int cascadeIndex, float value); - void setBiasInput(float input) { _biasInput = input; } - void calculateBiases(); + void calculateBiases(float biasInput); }; class RenderShadowCascadeSetup { diff --git a/scripts/developer/utilities/render/shadow.qml b/scripts/developer/utilities/render/shadow.qml index 427b52c659..ff50bf297c 100755 --- a/scripts/developer/utilities/render/shadow.qml +++ b/scripts/developer/utilities/render/shadow.qml @@ -117,17 +117,17 @@ Rectangle { max: 1.0 min: 0.0 height: 38 - width:250 + width: 250 } ConfigSlider { label: qsTr("Shadow Max Distance") integral: false config: shadowConfig - property: "globalMaxDistance" - max: 100.0 - min: 1.0 + property: "maxDistance" + max: 250.0 + min: 0.0 height: 38 - width:250 + width: 250 } Repeater { model: [ @@ -156,17 +156,17 @@ Rectangle { integral: false config: shadowConfig property: "constantBias"+modelData - max: 1.0 + max: 3.0 min: 0.0 height: 38 - width:250 + width: 250 } ConfigSlider { label: qsTr("Slope bias") integral: false config: shadowConfig property: "slopeBias"+modelData - max: 1.0 + max: 3.0 min: 0.0 height: 38 width: 250 diff --git a/scripts/simplifiedUI/system/html/js/entityProperties.js b/scripts/simplifiedUI/system/html/js/entityProperties.js index f7c440948f..76264429ac 100644 --- a/scripts/simplifiedUI/system/html/js/entityProperties.js +++ b/scripts/simplifiedUI/system/html/js/entityProperties.js @@ -319,7 +319,7 @@ const GROUPS = [ label: "Shadow Max Distance", type: "number-draggable", min: 0, - max: 500, + max: 250, step: 0.1, decimals: 2, propertyID: "keyLight.shadowMaxDistance", diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index f7c440948f..76264429ac 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -319,7 +319,7 @@ const GROUPS = [ label: "Shadow Max Distance", type: "number-draggable", min: 0, - max: 500, + max: 250, step: 0.1, decimals: 2, propertyID: "keyLight.shadowMaxDistance", From 732a7b0a89a2bcd52778eab0666bfe31f9fc2904 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 3 Jul 2019 22:43:35 -0700 Subject: [PATCH 08/77] fix build error --- libraries/render-utils/src/RenderShadowTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 802dc633bf..484064f73d 100755 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -405,8 +405,8 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c calculateBiases(biasInput > 0.0f ? biasInput : currentKeyLight->getShadowBias()); - std::array constantBiases = { constantBias0, constantBias1, constantBias2, constantBias3 }; - std::array slopeBiases = { slopeBias0, slopeBias1, slopeBias2, slopeBias3 }; + std::array constantBiases = {{ constantBias0, constantBias1, constantBias2, constantBias3 }}; + std::array slopeBiases = {{ slopeBias0, slopeBias1, slopeBias2, slopeBias3 }}; for (unsigned int cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { float constantBias = constantBiases[cascadeIndex]; if (constantBias > 0.0f) { From 68b2c8c2fbde0fdf58f1ce004c2a9f4bbcbe4f6f Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 9 Jul 2019 00:46:24 -0700 Subject: [PATCH 09/77] wip adding haze to forward rendering --- libraries/render-utils/src/GlobalLight.slh | 68 +------------------ .../src/directional_ambient_light.slf | 7 +- .../src/directional_ambient_light_shadow.slf | 7 +- .../src/directional_skybox_light.slf | 4 +- .../src/directional_skybox_light_shadow.slf | 8 +-- libraries/render-utils/src/model.slf | 6 +- libraries/render-utils/src/sdf_text3D.slf | 4 +- libraries/render-utils/src/simple.slf | 4 +- .../render-utils/src/simple_procedural.slf | 4 +- 9 files changed, 19 insertions(+), 93 deletions(-) diff --git a/libraries/render-utils/src/GlobalLight.slh b/libraries/render-utils/src/GlobalLight.slh index 1cc357fe5f..1c8914adf3 100644 --- a/libraries/render-utils/src/GlobalLight.slh +++ b/libraries/render-utils/src/GlobalLight.slh @@ -1,5 +1,5 @@ -<@if not HIFI_USE_FORWARD@> <@include Haze.slh@> -<@endif@> <@func declareEvalSkyboxGlobalColor(supportScattering)@> @@ -142,12 +140,10 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu color += directionalDiffuse; color += directionalSpecular; -<@if not HIFI_USE_FORWARD@> // Attenuate the light if haze effect selected if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); } -<@endif@> return color; } @@ -184,61 +180,7 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur <$declareLightingAmbient(1, 1, 1)$> <$declareLightingDirectional()$> -vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) { - <$prepareGlobalLight(position, normal)$> - - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); - - color += emissive * isEmissiveEnabled(); - - // Ambient - vec3 ambientDiffuse; - vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance); - color += ambientDiffuse; - - // Directional - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); - color += directionalDiffuse; - color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); - - return color; -} - -vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity, vec3 prevLighting) { - <$prepareGlobalLight(position, normal)$> - - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); - - color = prevLighting; - color += emissive * isEmissiveEnabled(); - - // Ambient - vec3 ambientDiffuse; - vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance); - color += ambientDiffuse; - - // Directional - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); - color += directionalDiffuse; - color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); - - return color; -} - -<@endfunc@> - -<@func declareEvalGlobalLightingAlphaBlendedWithHaze()@> - -<$declareLightingAmbient(1, 1, 1)$> -<$declareLightingDirectional()$> - -vec3 evalGlobalLightingAlphaBlendedWithHaze( +vec3 evalGlobalLightingAlphaBlended( mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) { @@ -261,7 +203,6 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( color += directionalDiffuse; color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); -<@if not HIFI_USE_FORWARD@> // Haze if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { vec4 hazeColor = computeHazeColor( @@ -273,12 +214,11 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( color = mix(color.rgb, hazeColor.rgb, hazeColor.a); } -<@endif@> return color; } -vec3 evalGlobalLightingAlphaBlendedWithHaze( +vec3 evalGlobalLightingAlphaBlended( mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) { @@ -300,7 +240,6 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( color += ambientDiffuse + directionalDiffuse; color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); -<@if not HIFI_USE_FORWARD@> // Haze if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { vec4 hazeColor = computeHazeColor( @@ -312,7 +251,6 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( color = mix(color.rgb, hazeColor.rgb, hazeColor.a); } -<@endif@> return color; } diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index ecacff38f6..dd1b59f43e 100644 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -11,15 +11,10 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - - - <@include DeferredBufferRead.slh@> -<@include GlobalLight.slh@> <@include render-utils/ShaderConstants.h@> -<$declareEvalLightmappedColor()$> - +<@include GlobalLight.slh@> <$declareEvalAmbientSphereGlobalColor(supportScattering)$> layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; diff --git a/libraries/render-utils/src/directional_ambient_light_shadow.slf b/libraries/render-utils/src/directional_ambient_light_shadow.slf index c6763eb372..34018125af 100644 --- a/libraries/render-utils/src/directional_ambient_light_shadow.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow.slf @@ -11,15 +11,14 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - -<@include Shadow.slh@> <@include DeferredBufferRead.slh@> -<@include GlobalLight.slh@> <@include render-utils/ShaderConstants.h@> -<$declareEvalLightmappedColor()$> +<@include GlobalLight.slh@> <$declareEvalAmbientSphereGlobalColor(isScattering)$> +<@include Shadow.slh@> + layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy #define _texCoord1 _texCoord01.zw diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index f6044b2d89..4ef7621b36 100644 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -11,12 +11,10 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - <@include DeferredBufferRead.slh@> -<@include GlobalLight.slh@> <@include render-utils/ShaderConstants.h@> -<$declareEvalLightmappedColor()$> +<@include GlobalLight.slh@> <$declareEvalSkyboxGlobalColor(isScattering)$> layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; diff --git a/libraries/render-utils/src/directional_skybox_light_shadow.slf b/libraries/render-utils/src/directional_skybox_light_shadow.slf index 7af0eafd9a..217cf3ba05 100644 --- a/libraries/render-utils/src/directional_skybox_light_shadow.slf +++ b/libraries/render-utils/src/directional_skybox_light_shadow.slf @@ -11,15 +11,14 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html //!> - -<@include Shadow.slh@> <@include DeferredBufferRead.slh@> -<@include GlobalLight.slh@> <@include render-utils/ShaderConstants.h@> -<$declareEvalLightmappedColor()$> +<@include GlobalLight.slh@> <$declareEvalSkyboxGlobalColor(isScattering)$> +<@include Shadow.slh@> + layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy #define _texCoord1 _texCoord01.zw @@ -35,7 +34,6 @@ void main(void) { vec3 worldLightDirection = getLightDirection(shadowLight); float shadowAttenuation = evalShadowAttenuation(worldLightDirection, worldPos, -viewPos.z, frag.normal); - // Light mapped or not ? if (frag.mode == FRAG_MODE_UNLIT || frag.mode == FRAG_MODE_LIGHTMAPPED) { discard; } else { diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index 374248765d..b3167dd598 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -23,10 +23,8 @@ <@elif HIFI_USE_TRANSLUCENT@> <@if not HIFI_USE_FORWARD@> <@include LightLocal.slh@> - <$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - <@else@> - <$declareEvalGlobalLightingAlphaBlended()$> <@endif@> + <$declareEvalGlobalLightingAlphaBlended()$> <@else@> <$declareEvalSkyboxGlobalColor()$> <@endif@> @@ -298,7 +296,7 @@ void main(void) { vec4(0), vec4(0), opacity); } - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, 1.0, occlusion, diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index c56c8b6436..a5a7cfb6a4 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -16,7 +16,7 @@ <@if HIFI_USE_FORWARD@> <$declareEvalSkyboxGlobalColor()$> <@else@> - <$declareEvalGlobalLightingAlphaBlendedWithHaze()$> + <$declareEvalGlobalLightingAlphaBlended()$> <@endif@> <@include gpu/Transform.slh@> @@ -78,7 +78,7 @@ void main() { DEFAULT_ROUGHNESS), alpha); <@else@> - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, 1.0, DEFAULT_OCCLUSION, diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index ce063cd7e7..ac7deedff0 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -31,7 +31,7 @@ <$declareEvalSkyboxGlobalColor()$> <@elif HIFI_USE_TRANSLUCENT@> <@include GlobalLight.slh@> - <$declareEvalGlobalLightingAlphaBlendedWithHaze()$> + <$declareEvalGlobalLightingAlphaBlended()$> <@else@> <@include DeferredBufferWrite.slh@> <@endif@> @@ -101,7 +101,7 @@ void main(void) { DEFAULT_ROUGHNESS), texel.a); <@elif HIFI_USE_TRANSLUCENT@> - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, 1.0, DEFAULT_OCCLUSION, diff --git a/libraries/render-utils/src/simple_procedural.slf b/libraries/render-utils/src/simple_procedural.slf index ae5b72012f..5b0eb62cca 100644 --- a/libraries/render-utils/src/simple_procedural.slf +++ b/libraries/render-utils/src/simple_procedural.slf @@ -16,7 +16,7 @@ <@include DefaultMaterials.slh@> <@include GlobalLight.slh@> - <$declareEvalGlobalLightingAlphaBlendedWithHaze()$> + <$declareEvalGlobalLightingAlphaBlended()$> layout(location=0) out vec4 _fragColor0; <@endif@> @@ -167,7 +167,7 @@ void main(void) { if (emissiveAmount > 0.0) { _fragColor0 = vec4(diffuse, alpha); } else { - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, 1.0, occlusion, From 8fd2251612f6747a212af072e01c4194c0823b82 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 9 Jul 2019 12:52:02 -0700 Subject: [PATCH 10/77] mostly working equation? --- libraries/graphics/src/graphics/Light.h | 2 +- libraries/render-utils/src/LightStage.cpp | 12 +++-- libraries/render-utils/src/LightStage.h | 3 +- .../render-utils/src/RenderShadowTask.cpp | 47 +++++++------------ libraries/render-utils/src/RenderShadowTask.h | 1 - .../src/directional_skybox_light_shadow.slf | 1 - scripts/developer/utilities/render/shadow.qml | 4 +- 7 files changed, 32 insertions(+), 38 deletions(-) diff --git a/libraries/graphics/src/graphics/Light.h b/libraries/graphics/src/graphics/Light.h index 37670176cc..81a6fddbd3 100755 --- a/libraries/graphics/src/graphics/Light.h +++ b/libraries/graphics/src/graphics/Light.h @@ -199,7 +199,7 @@ protected: float _spotCos { -1.0f }; // stored here to be able to reset the spot angle when turning the type spot on/off float _shadowsMaxDistance { 40.0f }; - float _shadowBias { 0.5f }; // 0.23f will roughly give the default constant and slope values + float _shadowBias { 0.5f }; bool _castShadows{ false }; void updateLightRadius(); diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 524deaaad2..ccdf45cedc 100755 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -16,7 +16,8 @@ #include "ViewFrustum.h" std::string LightStage::_stageName { "LIGHT_STAGE"}; -const glm::mat4 LightStage::Shadow::_biasMatrix{ +// The bias matrix goes from homogeneous coordinates to UV coords (see http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/#basic-shader) +const glm::mat4 LightStage::Shadow::_biasMatrix { 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, @@ -249,7 +250,7 @@ void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, } void LightStage::Shadow::setKeylightCascadeFrustum(unsigned int cascadeIndex, const ViewFrustum& viewFrustum, - float nearDepth, float farDepth, float fixedBias, float slopeBias) { + float nearDepth, float farDepth) { assert(nearDepth < farDepth); assert(cascadeIndex < _cascades.size()); @@ -300,7 +301,12 @@ void LightStage::Shadow::setKeylightCascadeFrustum(unsigned int cascadeIndex, co auto& schema = _schemaBuffer.edit(); auto& schemaCascade = schema.cascades[cascadeIndex]; schemaCascade.reprojection = _biasMatrix * ortho * shadowViewInverse.getMatrix(); - schemaCascade.fixedBias = fixedBias; +} + +void LightStage::Shadow::setKeylightCascadeBias(unsigned int cascadeIndex, float constantBias, float slopeBias) { + auto& schema = _schemaBuffer.edit(); + auto& schemaCascade = schema.cascades[cascadeIndex]; + schemaCascade.fixedBias = constantBias; schemaCascade.slopeBias = slopeBias; } diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 4da66843cc..36e62c614f 100755 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -81,7 +81,8 @@ public: void setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth = 1.0f, float farDepth = 1000.0f); void setKeylightCascadeFrustum(unsigned int cascadeIndex, const ViewFrustum& viewFrustum, - float nearDepth = 1.0f, float farDepth = 1000.0f, float fixedBias = 0.005f, float slopeBias = 0.005f); + float nearDepth = 1.0f, float farDepth = 1000.0f); + void setKeylightCascadeBias(unsigned int cascadeIndex, float constantBias, float slopeBias); void setCascadeFrustum(unsigned int cascadeIndex, const ViewFrustum& shadowFrustum); const UniformBufferView& getBuffer() const { return _schemaBuffer; } diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 484064f73d..0d0b776074 100755 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -329,37 +329,31 @@ void RenderShadowSetup::configure(const Config& config) { } void RenderShadowSetup::calculateBiases(float biasInput) { - // slope scaling values derived from ratio between original constantBias and slopeBias pairs - const std::array SLOPE_SCALES = {{ 2.7f, 3.0f, 3.7f, 3.5f }}; - const float CONVERT_BIAS = 100.0f; - const float MIN_SCALE_DIVISOR = 0.5f; - - // the bias is relative to resolution - // to remain consistent with the constant and slope bias values, the biasInput - // value is in the 0.0 - 1.0 range but needs to be scaled up for further calculations - // TODO: expose variable resolution - int resolution = LightStage::Shadow::MAP_SIZE; - const int DEFAULT_RESOLUTION = LightStage::Shadow::MAP_SIZE; - float inverseResolution = 1.0f / (float)resolution; - int resolutionScale = DEFAULT_RESOLUTION * inverseResolution; - float convertedBias = biasInput * (CONVERT_BIAS / resolutionScale); - float scaleFactor = 1.0f; + const std::array CONSTANT_CASCADE_SCALE = {{ 0.01f, 0.01f, 0.015f, 0.02f }}; + const float SLOPE_BIAS_SCALE = 0.005f; for (int i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) { - scaleFactor = convertedBias * (cacasdeDistances[0] / glm::max(MIN_SCALE_DIVISOR, cacasdeDistances[i + SHADOW_CASCADE_MAX_COUNT])) * inverseResolution; - float constantBias = cacasdeDistances[i] * scaleFactor; - float slopeBias = cacasdeDistances[i] * scaleFactor * SLOPE_SCALES[i]; + auto& cascade = _globalShadowObject->getCascade(i); + + // Constant bias is dependent on the depth precision + float cascadeDepth = cascade.getMaxDistance() - cascade.getMinDistance(); + float constantBias = CONSTANT_CASCADE_SCALE[i] * biasInput / cascadeDepth; setConstantBias(i, constantBias); - setSlopeBias(i, slopeBias); + + // Slope bias is dependent on the texel size + float cascadeWidth = cascade.getFrustum()->getWidth(); + float cascadeHeight = cascade.getFrustum()->getHeight(); + float cascadeTexelMaxDim = glm::max(cascadeWidth, cascadeHeight) / LightStage::Shadow::MAP_SIZE; // TODO: variable cascade resolution + setSlopeBias(i, cascadeTexelMaxDim * constantBias / SLOPE_BIAS_SCALE); } } void RenderShadowSetup::setConstantBias(int cascadeIndex, float value) { - _bias[cascadeIndex]._constant = value * value * value * 0.004f; + _bias[cascadeIndex]._constant = value; } void RenderShadowSetup::setSlopeBias(int cascadeIndex, float value) { - _bias[cascadeIndex]._slope = value * value * value * 0.001f; + _bias[cascadeIndex]._slope = value; } void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { @@ -398,9 +392,9 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c // Update our biases and maxDistance from the light or config _globalShadowObject->setMaxDistance(maxDistance > 0.0f ? maxDistance : currentKeyLight->getShadowsMaxDistance()); + // Adjust each cascade frustum for (unsigned int cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { - cacasdeDistances[cascadeIndex] = _globalShadowObject->getCascade(cascadeIndex).getMaxDistance(); - cacasdeDistances[cascadeIndex + SHADOW_CASCADE_MAX_COUNT] = _globalShadowObject->getCascade(cascadeIndex).getMinDistance(); + _globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); } calculateBiases(biasInput > 0.0f ? biasInput : currentKeyLight->getShadowBias()); @@ -416,14 +410,9 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c if (slopeBias > 0.0f) { setSlopeBias(cascadeIndex, slopeBias); } - } - // Adjust each cascade frustum - for (unsigned int cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { auto& bias = _bias[cascadeIndex]; - _globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(), - SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR, - bias._constant, bias._slope); + _globalShadowObject->setKeylightCascadeBias(cascadeIndex, bias._constant, bias._slope); } _shadowFrameCache->pushShadow(_globalShadowObject); diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 23047ee179..98b5ac1e10 100755 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -138,7 +138,6 @@ private: float slopeBias3; float biasInput; float maxDistance; - std::array cacasdeDistances; // 4 max then 4 min distances void setConstantBias(int cascadeIndex, float value); void setSlopeBias(int cascadeIndex, float value); diff --git a/libraries/render-utils/src/directional_skybox_light_shadow.slf b/libraries/render-utils/src/directional_skybox_light_shadow.slf index 8716d60d54..48d59fa364 100644 --- a/libraries/render-utils/src/directional_skybox_light_shadow.slf +++ b/libraries/render-utils/src/directional_skybox_light_shadow.slf @@ -35,7 +35,6 @@ void main(void) { vec3 worldLightDirection = getLightDirection(shadowLight); float shadowAttenuation = evalShadowAttenuation(worldLightDirection, worldPos, -viewPos.z, frag.normal); - // Light mapped or not ? if (frag.mode == FRAG_MODE_UNLIT || frag.mode == FRAG_MODE_LIGHTMAPPED) { discard; } else { diff --git a/scripts/developer/utilities/render/shadow.qml b/scripts/developer/utilities/render/shadow.qml index ff50bf297c..6af0b21d1b 100755 --- a/scripts/developer/utilities/render/shadow.qml +++ b/scripts/developer/utilities/render/shadow.qml @@ -156,7 +156,7 @@ Rectangle { integral: false config: shadowConfig property: "constantBias"+modelData - max: 3.0 + max: 1.0 min: 0.0 height: 38 width: 250 @@ -166,7 +166,7 @@ Rectangle { integral: false config: shadowConfig property: "slopeBias"+modelData - max: 3.0 + max: 1.0 min: 0.0 height: 38 width: 250 From 520c62f6f65f9037f7f573cb2bee37b36bc541f3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 3 Jul 2019 13:59:11 -0700 Subject: [PATCH 11/77] wait for objects added to physics before stop SafeLanding --- interface/src/avatar/OtherAvatar.cpp | 1 + interface/src/octree/SafeLanding.cpp | 10 +++--- .../src/RenderableModelEntityItem.cpp | 35 ++++++++++--------- .../src/RenderableModelEntityItem.h | 7 ++-- libraries/entities/src/ModelEntityItem.cpp | 4 --- libraries/entities/src/ModelEntityItem.h | 3 -- .../physics/src/PhysicalEntitySimulation.cpp | 16 +++++++-- libraries/workload/src/workload/Region.h | 3 +- .../workload/src/workload/RegionState.cpp | 4 ++- libraries/workload/src/workload/RegionState.h | 2 +- .../workload/src/workload/RegionTracker.cpp | 6 ++-- libraries/workload/src/workload/Space.cpp | 2 +- 12 files changed, 54 insertions(+), 39 deletions(-) diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index a6e2d6a998..3776d54d9a 100755 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -201,6 +201,7 @@ void OtherAvatar::computeShapeLOD() { break; case workload::Region::UNKNOWN: case workload::Region::INVALID: + case workload::Region::R4: case workload::Region::R3: default: newLOD = BodyLOD::Sphere; diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 75e512232b..01ef9ed69e 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -122,9 +122,6 @@ void SafeLanding::updateTracking() { if (isEntityPhysicsReady(entity) && isVisuallyReady) { entityMapIter = _trackedEntities.erase(entityMapIter); } else { - if (!isVisuallyReady) { - entity->requestRenderUpdate(); - } entityMapIter++; } } @@ -203,8 +200,11 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) { if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) { auto space = _entityTreeRenderer->getWorkloadSpace(); uint8_t region = space ? space->getRegion(entity->getSpaceIndex()) : (uint8_t)workload::Region::INVALID; - bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical(); - return (!shouldBePhysical || entity->isInPhysicsSimulation() || modelEntity->computeShapeFailedToLoad()); + bool definitelyNotPhysical = (region > workload::Region::R2 && region < workload::Region::UNKNOWN) || + !entity->shouldBePhysical() || + modelEntity->unableToLoadCollisionShape(); + bool definitelyPhysical = entity->isInPhysicsSimulation(); + return definitelyNotPhysical || definitelyPhysical; } } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index cfc94ad92c..7ef491312f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -282,27 +282,26 @@ bool RenderableModelEntityItem::findDetailedParabolaIntersection(const glm::vec3 } void RenderableModelEntityItem::fetchCollisionGeometryResource() { - _compoundShapeResource = DependencyManager::get()->getCollisionGeometryResource(getCollisionShapeURL()); + _collisionGeometryResource = DependencyManager::get()->getCollisionGeometryResource(getCollisionShapeURL()); } -bool RenderableModelEntityItem::computeShapeFailedToLoad() { - if (!_compoundShapeResource) { +bool RenderableModelEntityItem::unableToLoadCollisionShape() { + if (!_collisionGeometryResource) { fetchCollisionGeometryResource(); } - - return (_compoundShapeResource && _compoundShapeResource->isFailed()); + return (_collisionGeometryResource && _collisionGeometryResource->isFailed()); } void RenderableModelEntityItem::setShapeType(ShapeType type) { ModelEntityItem::setShapeType(type); auto shapeType = getShapeType(); if (shapeType == SHAPE_TYPE_COMPOUND || shapeType == SHAPE_TYPE_SIMPLE_COMPOUND) { - if (!_compoundShapeResource && !getCollisionShapeURL().isEmpty()) { + if (!_collisionGeometryResource && !getCollisionShapeURL().isEmpty()) { fetchCollisionGeometryResource(); } - } else if (_compoundShapeResource && !getCompoundShapeURL().isEmpty()) { + } else if (_collisionGeometryResource && !getCompoundShapeURL().isEmpty()) { // the compoundURL has been set but the shapeType does not agree - _compoundShapeResource.reset(); + _collisionGeometryResource.reset(); } } @@ -333,11 +332,11 @@ bool RenderableModelEntityItem::isReadyToComputeShape() const { } if (model->isLoaded()) { - if (!shapeURL.isEmpty() && !_compoundShapeResource) { + if (!shapeURL.isEmpty() && !_collisionGeometryResource) { const_cast(this)->fetchCollisionGeometryResource(); } - if (_compoundShapeResource && _compoundShapeResource->isLoaded()) { + if (_collisionGeometryResource && _collisionGeometryResource->isLoaded()) { // we have both URLs AND both geometries AND they are both fully loaded. if (_needsInitialSimulation) { // the _model's offset will be wrong until _needsInitialSimulation is false @@ -368,7 +367,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { } if (type == SHAPE_TYPE_COMPOUND) { - if (!_compoundShapeResource || !_compoundShapeResource->isLoaded()) { + if (!_collisionGeometryResource || !_collisionGeometryResource->isLoaded()) { return; } @@ -376,8 +375,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { // should never fall in here when collision model not fully loaded // TODO: assert that all geometries exist and are loaded - //assert(_model && _model->isLoaded() && _compoundShapeResource && _compoundShapeResource->isLoaded()); - const HFMModel& collisionGeometry = _compoundShapeResource->getHFMModel(); + //assert(_model && _model->isLoaded() && _collisionGeometryResource && _collisionGeometryResource->isLoaded()); + const HFMModel& collisionGeometry = _collisionGeometryResource->getHFMModel(); ShapeInfo::PointCollection& pointCollection = shapeInfo.getPointCollection(); pointCollection.clear(); @@ -499,7 +498,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { std::vector> meshes; if (type == SHAPE_TYPE_SIMPLE_COMPOUND) { - auto& hfmMeshes = _compoundShapeResource->getHFMModel().meshes; + auto& hfmMeshes = _collisionGeometryResource->getHFMModel().meshes; meshes.reserve(hfmMeshes.size()); for (auto& hfmMesh : hfmMeshes) { meshes.push_back(hfmMesh._mesh); @@ -727,10 +726,10 @@ int RenderableModelEntityItem::avatarJointIndex(int modelJointIndex) { bool RenderableModelEntityItem::contains(const glm::vec3& point) const { auto model = getModel(); - if (EntityItem::contains(point) && model && _compoundShapeResource && _compoundShapeResource->isLoaded()) { + if (EntityItem::contains(point) && model && _collisionGeometryResource && _collisionGeometryResource->isLoaded()) { glm::mat4 worldToHFMMatrix = model->getWorldToHFMMatrix(); glm::vec3 hfmPoint = worldToHFMMatrix * glm::vec4(point, 1.0f); - return _compoundShapeResource->getHFMModel().convexHullContains(hfmPoint); + return _collisionGeometryResource->getHFMModel().convexHullContains(hfmPoint); } return false; @@ -960,6 +959,10 @@ QStringList RenderableModelEntityItem::getJointNames() const { return result; } +QString RenderableModelEntityItem::getCollisionShapeURL() const { + return getShapeType() == SHAPE_TYPE_COMPOUND ? getCompoundShapeURL() : getModelURL(); +} + scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel() { auto model = resultWithReadLock([this]{ return _model; }); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 7f84b3ae62..3c6f1d956c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -79,7 +79,7 @@ public: virtual bool isReadyToComputeShape() const override; virtual void computeShapeInfo(ShapeInfo& shapeInfo) override; - bool computeShapeFailedToLoad(); + bool unableToLoadCollisionShape(); virtual bool contains(const glm::vec3& point) const override; void stopModelOverrideIfNoParent(); @@ -113,6 +113,9 @@ public: virtual int getJointIndex(const QString& name) const override; virtual QStringList getJointNames() const override; + // Returns the URL used for the collision shape + QString getCollisionShapeURL() const; + private: bool needsUpdateModelBounds() const; void autoResizeJointArrays(); @@ -120,7 +123,7 @@ private: bool readyToAnimate() const; void fetchCollisionGeometryResource(); - GeometryResource::Pointer _compoundShapeResource; + GeometryResource::Pointer _collisionGeometryResource; std::vector _jointMap; QVariantMap _originalTextures; bool _jointMapCompleted { false }; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index f276bea05d..346a05a1bf 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -590,10 +590,6 @@ QString ModelEntityItem::getCompoundShapeURL() const { return _compoundShapeURL.get(); } -QString ModelEntityItem::getCollisionShapeURL() const { - return getShapeType() == SHAPE_TYPE_COMPOUND ? getCompoundShapeURL() : getModelURL(); -} - void ModelEntityItem::setColor(const glm::u8vec3& value) { withWriteLock([&] { _color = value; diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 75a695f1c0..d9a7e5a743 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -75,9 +75,6 @@ public: static const QString DEFAULT_COMPOUND_SHAPE_URL; QString getCompoundShapeURL() const; - // Returns the URL used for the collision shape - QString getCollisionShapeURL() const; - // model related properties virtual void setModelURL(const QString& url); virtual void setCompoundShapeURL(const QString& url); diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 0a08aaa28d..85c53af10a 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -49,9 +49,9 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) { assert(entity); assert(!entity->isDead()); uint8_t region = _space->getRegion(entity->getSpaceIndex()); - bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical(); + bool maybeShouldBePhysical = (region < workload::Region::R3 || region == workload::Region::UNKNOWN) && entity->shouldBePhysical(); bool canBeKinematic = region <= workload::Region::R3; - if (shouldBePhysical) { + if (maybeShouldBePhysical) { EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); if (motionState) { motionState->setRegion(region); @@ -330,6 +330,18 @@ void PhysicalEntitySimulation::buildMotionStatesForEntitiesThatNeedThem() { continue; } + uint8_t region = _space->getRegion(entity->getSpaceIndex()); + if (region == workload::Region::UNKNOWN) { + // the workload hasn't categorized it yet --> skip for later + ++entityItr; + continue; + } + if (region > workload::Region::R2) { + // not in physical zone --> remove from list + entityItr = _entitiesToAddToPhysics.erase(entityItr); + continue; + } + if (entity->isReadyToComputeShape()) { ShapeRequest shapeRequest(entity); ShapeRequests::iterator requestItr = _shapeRequests.find(shapeRequest); diff --git a/libraries/workload/src/workload/Region.h b/libraries/workload/src/workload/Region.h index 43aed9aef4..0262899d01 100644 --- a/libraries/workload/src/workload/Region.h +++ b/libraries/workload/src/workload/Region.h @@ -21,6 +21,7 @@ public: R1 = 0, R2, R3, + R4, UNKNOWN, INVALID, }; @@ -71,4 +72,4 @@ inline uint8_t Region::computeTransitionIndex(uint8_t prevIndex, uint8_t newInde } // namespace workload -#endif // hifi_workload_Region_h \ No newline at end of file +#endif // hifi_workload_Region_h diff --git a/libraries/workload/src/workload/RegionState.cpp b/libraries/workload/src/workload/RegionState.cpp index 47179ad6f7..ade7e47e4d 100644 --- a/libraries/workload/src/workload/RegionState.cpp +++ b/libraries/workload/src/workload/RegionState.cpp @@ -28,7 +28,9 @@ void RegionState::run(const workload::WorkloadContextPointer& renderContext, con // ... // inputs[2N] = vector of ids exiting region N // inputs[2N + 1] = vector of ids entering region N - assert(inputs.size() == 2 * Region::UNKNOWN); + // + // But we only pass inputs for R1 through R3 + assert(inputs.size() == 2 * (int32_t)(Region::R3 + 1)); // The id's in each vector are sorted in ascending order // because the source vectors are scanned in ascending order. diff --git a/libraries/workload/src/workload/RegionState.h b/libraries/workload/src/workload/RegionState.h index 40db9d4982..9552709d8e 100644 --- a/libraries/workload/src/workload/RegionState.h +++ b/libraries/workload/src/workload/RegionState.h @@ -54,7 +54,7 @@ namespace workload { using JobModel = workload::Job::ModelI; RegionState() { - _state.resize(Region::UNKNOWN); + _state.resize(Region::R3 + 1); } void configure(const Config& config); diff --git a/libraries/workload/src/workload/RegionTracker.cpp b/libraries/workload/src/workload/RegionTracker.cpp index 381b92c414..0866c91709 100644 --- a/libraries/workload/src/workload/RegionTracker.cpp +++ b/libraries/workload/src/workload/RegionTracker.cpp @@ -33,15 +33,15 @@ void RegionTracker::run(const WorkloadContextPointer& context, Outputs& outputs) //Changes changes; space->categorizeAndGetChanges(outChanges); - // use exit/enter lists for each region less than Region::UNKNOWN + // use exit/enter lists for each region less than Region::R4 outRegionChanges.resize(2 * (workload::Region::NUM_CLASSIFICATIONS - 1)); for (uint32_t i = 0; i < outChanges.size(); ++i) { Space::Change& change = outChanges[i]; - if (change.prevRegion < Region::UNKNOWN) { + if (change.prevRegion < Region::R4) { // EXIT list index = 2 * regionIndex outRegionChanges[2 * change.prevRegion].push_back(change.proxyId); } - if (change.region < Region::UNKNOWN) { + if (change.region < Region::R4) { // ENTER list index = 2 * regionIndex + 1 outRegionChanges[2 * change.region + 1].push_back(change.proxyId); } diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 747df5f6c4..f045c8311f 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -99,7 +99,7 @@ void Space::categorizeAndGetChanges(std::vector& changes) { if (proxy.region < Region::INVALID) { glm::vec3 proxyCenter = glm::vec3(proxy.sphere); float proxyRadius = proxy.sphere.w; - uint8_t region = Region::UNKNOWN; + uint8_t region = Region::R4; for (uint32_t j = 0; j < numViews; ++j) { auto& view = _views[j]; // for each 'view' we need only increment 'k' below the current value of 'region' From 1bfd5386a90f8c179ef9e9dd96ed576ca3cd862d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 8 Jul 2019 09:37:26 -0700 Subject: [PATCH 12/77] restore entity->requestRenderUpdate() in SafeLanding::updateTracking() --- interface/src/octree/SafeLanding.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 01ef9ed69e..00ac958b14 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -122,6 +122,9 @@ void SafeLanding::updateTracking() { if (isEntityPhysicsReady(entity) && isVisuallyReady) { entityMapIter = _trackedEntities.erase(entityMapIter); } else { + if (!isVisuallyReady) { + entity->requestRenderUpdate(); + } entityMapIter++; } } From 0f42dca40b5ae091a3ff8e2d89fe23190c557a26 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 9 Jul 2019 15:13:49 -0700 Subject: [PATCH 13/77] add some comments about meanings of workload Regions --- libraries/workload/src/workload/Region.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/workload/src/workload/Region.h b/libraries/workload/src/workload/Region.h index 0262899d01..6ee3b775ee 100644 --- a/libraries/workload/src/workload/Region.h +++ b/libraries/workload/src/workload/Region.h @@ -18,12 +18,12 @@ public: using Type = uint8_t; enum Name : uint8_t { - R1 = 0, - R2, - R3, - R4, - UNKNOWN, - INVALID, + R1 = 0, // R1 = in physics simulation and client will bid for simulation ownership + R2, // R2 = in physics simulation but client prefers to NOT have simulation ownership + R3, // R3 = are NOT in physics simulation but yes kinematically animated when velocities are non-zero + R4, // R4 = known to workload but outside R3, not in physics, not animated if moving + UNKNOWN, // UNKNOWN = known to workload but unsorted + INVALID, // INVALID = not known to workload }; static const uint8_t NUM_CLASSIFICATIONS = 4; From f44551e957a4d9cb4c5af268c5189e033b088bdc Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 9 Jul 2019 15:14:18 -0700 Subject: [PATCH 14/77] more readable code --- libraries/workload/src/workload/RegionState.cpp | 2 +- libraries/workload/src/workload/RegionState.h | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/workload/src/workload/RegionState.cpp b/libraries/workload/src/workload/RegionState.cpp index ade7e47e4d..509c00a048 100644 --- a/libraries/workload/src/workload/RegionState.cpp +++ b/libraries/workload/src/workload/RegionState.cpp @@ -30,7 +30,7 @@ void RegionState::run(const workload::WorkloadContextPointer& renderContext, con // inputs[2N + 1] = vector of ids entering region N // // But we only pass inputs for R1 through R3 - assert(inputs.size() == 2 * (int32_t)(Region::R3 + 1)); + assert(inputs.size() == 2 * RegionState::NUM_REGIONS_TRACKED); // The id's in each vector are sorted in ascending order // because the source vectors are scanned in ascending order. diff --git a/libraries/workload/src/workload/RegionState.h b/libraries/workload/src/workload/RegionState.h index 9552709d8e..d941a5046c 100644 --- a/libraries/workload/src/workload/RegionState.h +++ b/libraries/workload/src/workload/RegionState.h @@ -53,8 +53,11 @@ namespace workload { using Inputs = IndexVectors; using JobModel = workload::Job::ModelI; + // we track Proxies in regions R1 through R3 + const uint32_t NUM_REGIONS_TRACKED = uint32_t(Region::R3 - Region::R1 + 1); + RegionState() { - _state.resize(Region::R3 + 1); + _state.resize(NUM_REGIONS_TRACKED); } void configure(const Config& config); From 2da0714e36b30967dcb9b0beff341b2b23c45859 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 9 Jul 2019 15:30:06 -0700 Subject: [PATCH 15/77] comments and more readable code --- interface/src/octree/SafeLanding.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 00ac958b14..88807fc577 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -203,7 +203,18 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) { if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) { auto space = _entityTreeRenderer->getWorkloadSpace(); uint8_t region = space ? space->getRegion(entity->getSpaceIndex()) : (uint8_t)workload::Region::INVALID; - bool definitelyNotPhysical = (region > workload::Region::R2 && region < workload::Region::UNKNOWN) || + + // Note: the meanings of the workload regions are: + // R1 = in physics simulation and willing to own simulation + // R2 = in physics simulation but does NOT want to own simulation + // R3 = not in physics simulation but kinematically animated when velocities are non-zero + // R4 = sorted by workload and found to be outside R3 + // UNKNOWN = known to workload but not yet sorted + // INVALID = not known to workload + // So any entity sorted into R3 or R4 is definitelyNotPhysical + + bool definitelyNotPhysical = region == workload::Region::R2 || + region == workload::Region::R4 || !entity->shouldBePhysical() || modelEntity->unableToLoadCollisionShape(); bool definitelyPhysical = entity->isInPhysicsSimulation(); From 9a6b42ec288bd6e76c434906801687856d8bde95 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 9 Jul 2019 15:45:41 -0700 Subject: [PATCH 16/77] move getCollisionShapeURL() back to base class --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 4 ---- libraries/entities-renderer/src/RenderableModelEntityItem.h | 3 --- libraries/entities/src/ModelEntityItem.cpp | 4 ++++ libraries/entities/src/ModelEntityItem.h | 3 +++ 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 7ef491312f..9d23bd09ad 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -959,10 +959,6 @@ QStringList RenderableModelEntityItem::getJointNames() const { return result; } -QString RenderableModelEntityItem::getCollisionShapeURL() const { - return getShapeType() == SHAPE_TYPE_COMPOUND ? getCompoundShapeURL() : getModelURL(); -} - scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel() { auto model = resultWithReadLock([this]{ return _model; }); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 3c6f1d956c..c32dad901f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -113,9 +113,6 @@ public: virtual int getJointIndex(const QString& name) const override; virtual QStringList getJointNames() const override; - // Returns the URL used for the collision shape - QString getCollisionShapeURL() const; - private: bool needsUpdateModelBounds() const; void autoResizeJointArrays(); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 346a05a1bf..f276bea05d 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -590,6 +590,10 @@ QString ModelEntityItem::getCompoundShapeURL() const { return _compoundShapeURL.get(); } +QString ModelEntityItem::getCollisionShapeURL() const { + return getShapeType() == SHAPE_TYPE_COMPOUND ? getCompoundShapeURL() : getModelURL(); +} + void ModelEntityItem::setColor(const glm::u8vec3& value) { withWriteLock([&] { _color = value; diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index d9a7e5a743..75a695f1c0 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -75,6 +75,9 @@ public: static const QString DEFAULT_COMPOUND_SHAPE_URL; QString getCompoundShapeURL() const; + // Returns the URL used for the collision shape + QString getCollisionShapeURL() const; + // model related properties virtual void setModelURL(const QString& url); virtual void setCompoundShapeURL(const QString& url); From 7c024b4e8aa3e49fa1d78c6152fdc2dfb57764e6 Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Thu, 13 Jun 2019 11:37:42 -0700 Subject: [PATCH 17/77] fix interactive window crash --- .../scripting/DesktopScriptingInterface.cpp | 19 ++- .../src/scripting/DesktopScriptingInterface.h | 2 + interface/src/ui/InteractiveWindow.cpp | 114 ++++-------------- 3 files changed, 45 insertions(+), 90 deletions(-) diff --git a/interface/src/scripting/DesktopScriptingInterface.cpp b/interface/src/scripting/DesktopScriptingInterface.cpp index ef5bd7abb9..678e698033 100644 --- a/interface/src/scripting/DesktopScriptingInterface.cpp +++ b/interface/src/scripting/DesktopScriptingInterface.cpp @@ -111,10 +111,11 @@ void DesktopScriptingInterface::show(const QString& path, const QString& title) InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString& sourceUrl, const QVariantMap& properties) { if (QThread::currentThread() != thread()) { InteractiveWindowPointer interactiveWindow = nullptr; - BLOCKING_INVOKE_METHOD(this, "createWindow", + BLOCKING_INVOKE_METHOD(this, "createWindowOnThread", Q_RETURN_ARG(InteractiveWindowPointer, interactiveWindow), Q_ARG(QString, sourceUrl), - Q_ARG(QVariantMap, properties)); + Q_ARG(QVariantMap, properties), + Q_ARG(QThread*, QThread::currentThread())); return interactiveWindow; } @@ -129,3 +130,17 @@ InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString& return new InteractiveWindow(sourceUrl, properties); } + +InteractiveWindowPointer DesktopScriptingInterface::createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread) { + + // The offscreen surface already validates against non-local QML sources, but we also need to ensure that + // if we create top level QML, like dock widgets or other types of QQuickView containing desktop windows + // that the source URL is permitted + const auto& urlValidator = OffscreenQmlSurface::getUrlValidator(); + if (!urlValidator(sourceUrl)) { + return nullptr; + } + InteractiveWindowPointer window = new InteractiveWindow(sourceUrl, properties); + window->moveToThread(targetThread); + return window; +} diff --git a/interface/src/scripting/DesktopScriptingInterface.h b/interface/src/scripting/DesktopScriptingInterface.h index b4ff159176..525fd7c803 100644 --- a/interface/src/scripting/DesktopScriptingInterface.h +++ b/interface/src/scripting/DesktopScriptingInterface.h @@ -101,6 +101,8 @@ private: static int flagAlwaysOnTop() { return AlwaysOnTop; } static int flagCloseButtonHides() { return CloseButtonHides; } + Q_INVOKABLE InteractiveWindowPointer createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread); + static QVariantMap getDockArea(); Q_INVOKABLE static QVariantMap getPresentationMode(); diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index dfef16b536..c85d7bc301 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -85,13 +85,13 @@ void InteractiveWindow::forwardKeyReleaseEvent(int key, int modifiers) { * @property {string} [title="InteractiveWindow] - The title of the window. * @property {Vec2} [position] - The initial position of the window, in pixels. * @property {Vec2} [size] - The initial size of the window, in pixels - * @property {boolean} [visible=true] - true to make the window visible when created, false to make + * @property {boolean} [visible=true] - true to make the window visible when created, false to make * it invisible. - * @property {InteractiveWindow.PresentationMode} [presentationMode=Desktop.PresentationMode.VIRTUAL] - - * Desktop.PresentationMode.VIRTUAL to display the window inside Interface, .NATIVE to display it + * @property {InteractiveWindow.PresentationMode} [presentationMode=Desktop.PresentationMode.VIRTUAL] - + * Desktop.PresentationMode.VIRTUAL to display the window inside Interface, .NATIVE to display it * as its own separate window. - * @property {InteractiveWindow.PresentationWindowInfo} [presentationWindowInfo] - Controls how a NATIVE window is - * displayed. If used, the window is docked to the specified edge of the Interface window, otherwise the window is + * @property {InteractiveWindow.PresentationWindowInfo} [presentationWindowInfo] - Controls how a NATIVE window is + * displayed. If used, the window is docked to the specified edge of the Interface window, otherwise the window is * displayed as its own separate window. * @property {InteractiveWindow.AdditionalFlags} [additionalFlags=0] - Window behavior flags in addition to "native window flags" (minimize/maximize/close), * set at window creation. Possible flag values are provided as {@link Desktop|Desktop.ALWAYS_ON_TOP} and {@link Desktop|Desktop.CLOSE_BUTTON_HIDES}. @@ -124,7 +124,7 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap auto mainWindow = qApp->getWindow(); _dockWidget = std::shared_ptr(new DockWidget(title, mainWindow), dockWidgetDeleter); auto quickView = _dockWidget->getQuickView(); - + Application::setupQmlSurface(quickView->rootContext() , true); //add any whitelisted callbacks @@ -176,7 +176,6 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap }); _dockWidget->setSource(QUrl(sourceUrl)); - mainWindow->addDockWidget(dockArea, _dockWidget.get()); } else { auto offscreenUi = DependencyManager::get(); @@ -254,55 +253,35 @@ void InteractiveWindow::sendToQml(const QVariant& message) { } void InteractiveWindow::emitScriptEvent(const QVariant& scriptMessage) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, scriptMessage)); - } else { - emit scriptEventReceived(scriptMessage); - } + emit scriptEventReceived(scriptMessage); } void InteractiveWindow::emitWebEvent(const QVariant& webMessage) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "emitWebEvent", Qt::QueuedConnection, Q_ARG(QVariant, webMessage)); - } else { - emit webEventReceived(webMessage); - } + emit webEventReceived(webMessage); } void InteractiveWindow::close() { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "close"); - return; - } - if (_qmlWindow) { _qmlWindow->deleteLater(); } - qApp->getWindow()->removeDockWidget(_dockWidget.get()); + if (_dockWidget) { + auto window = qApp->getWindow(); + BLOCKING_INVOKE_METHOD(window, "removeDockWidget", Q_ARG(QDockWidget*, _dockWidget.get())); + } _dockWidget = nullptr; _qmlWindow = nullptr; } void InteractiveWindow::show() { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "show"); - return; - } - if (_qmlWindow) { - QMetaObject::invokeMethod(_qmlWindow, "show", Qt::DirectConnection); + QMetaObject::invokeMethod(_qmlWindow, "show"); } } void InteractiveWindow::raise() { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "raise"); - return; - } - if (_qmlWindow) { - QMetaObject::invokeMethod(_qmlWindow, "raiseWindow", Qt::DirectConnection); + QMetaObject::invokeMethod(_qmlWindow, "raiseWindow"); } } @@ -323,17 +302,12 @@ void InteractiveWindow::setVisible(bool visible) { } if (!_qmlWindow.isNull()) { - _qmlWindow->setProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY, visible); + QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_VISIBLE_PROPERTY), + Q_ARG(bool, visible)); } } bool InteractiveWindow::isVisible() const { - if (QThread::currentThread() != thread()) { - bool result = false; - BLOCKING_INVOKE_METHOD(const_cast(this), "isVisible", Q_RETURN_ARG(bool, result)); - return result; - } - if (_qmlWindow.isNull()) { return false; } @@ -342,12 +316,6 @@ bool InteractiveWindow::isVisible() const { } glm::vec2 InteractiveWindow::getPosition() const { - if (QThread::currentThread() != thread()) { - glm::vec2 result; - BLOCKING_INVOKE_METHOD(const_cast(this), "getPosition", Q_RETURN_ARG(glm::vec2, result)); - return result; - } - if (_qmlWindow.isNull()) { return {}; } @@ -362,18 +330,13 @@ void InteractiveWindow::setPosition(const glm::vec2& position) { } if (!_qmlWindow.isNull()) { - _qmlWindow->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y)); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode", Qt::DirectConnection); + QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_POSITION_PROPERTY), + Q_ARG(QPointF, QPointF(position.x, position.y))); + QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode"); } } glm::vec2 InteractiveWindow::getSize() const { - if (QThread::currentThread() != thread()) { - glm::vec2 result; - BLOCKING_INVOKE_METHOD(const_cast(this), "getSize", Q_RETURN_ARG(glm::vec2, result)); - return result; - } - if (_qmlWindow.isNull()) { return {}; } @@ -381,24 +344,14 @@ glm::vec2 InteractiveWindow::getSize() const { } void InteractiveWindow::setSize(const glm::vec2& size) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setSize", Q_ARG(const glm::vec2&, size)); - return; - } - if (!_qmlWindow.isNull()) { - _qmlWindow->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y)); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode", Qt::DirectConnection); + QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_SIZE_PROPERTY), + Q_ARG(QSize, QSize(size.x, size.y))); + QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode"); } } QString InteractiveWindow::getTitle() const { - if (QThread::currentThread() != thread()) { - QString result; - BLOCKING_INVOKE_METHOD(const_cast(this), "getTitle", Q_RETURN_ARG(QString, result)); - return result; - } - if (_qmlWindow.isNull()) { return QString(); } @@ -406,24 +359,13 @@ QString InteractiveWindow::getTitle() const { } void InteractiveWindow::setTitle(const QString& title) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setTitle", Q_ARG(const QString&, title)); - return; - } - if (!_qmlWindow.isNull()) { - _qmlWindow->setProperty(TITLE_PROPERTY, title); + QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, TITLE_PROPERTY), + Q_ARG(QString, title)); } } int InteractiveWindow::getPresentationMode() const { - if (QThread::currentThread() != thread()) { - int result; - BLOCKING_INVOKE_METHOD(const_cast(this), "getPresentationMode", - Q_RETURN_ARG(int, result)); - return result; - } - if (_qmlWindow.isNull()) { return Virtual; } @@ -449,12 +391,8 @@ void InteractiveWindow::parentNativeWindowToMainWindow() { } void InteractiveWindow::setPresentationMode(int presentationMode) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setPresentationMode", Q_ARG(int, presentationMode)); - return; - } - if (!_qmlWindow.isNull()) { - _qmlWindow->setProperty(PRESENTATION_MODE_PROPERTY, presentationMode); + QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, PRESENTATION_MODE_PROPERTY), + Q_ARG(int, presentationMode)); } } From 1a5a925a4ceccb8fac4fb43eaa3b67009f696c80 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 10 Jul 2019 14:18:34 -0700 Subject: [PATCH 18/77] fix a typo --- interface/src/octree/SafeLanding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 88807fc577..80ca0e5398 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -213,7 +213,7 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) { // INVALID = not known to workload // So any entity sorted into R3 or R4 is definitelyNotPhysical - bool definitelyNotPhysical = region == workload::Region::R2 || + bool definitelyNotPhysical = region == workload::Region::R3 || region == workload::Region::R4 || !entity->shouldBePhysical() || modelEntity->unableToLoadCollisionShape(); From 4caa00d6cc0707dec74c4b5edb384b4569c6c372 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 10 Jul 2019 16:42:48 -0700 Subject: [PATCH 19/77] Start BUGZ-814: Start working on a new Graphics dialog for Metaverse version of Interface --- .../dialogs/graphics/GraphicsSettings.qml | 158 ++++++++++++++++++ interface/src/Menu.cpp | 9 +- 2 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml diff --git a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml new file mode 100644 index 0000000000..530b125ffc --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml @@ -0,0 +1,158 @@ +// +// GraphicsSettings.qml +// qml\hifi\dialogs\graphics +// +// Created by Zach Fox on 2019-07-10 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import Hifi 1.0 as Hifi +import QtQuick 2.10 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.12 +import stylesUit 1.0 as HifiStylesUit +import controlsUit 1.0 as HifiControlsUit +import "qrc:////qml//controls" as HifiControls + +Flickable { + HifiStylesUit.HifiConstants { id: hifi; } + + id: root; + contentWidth: parent.width + contentHeight: graphicsSettingsColumnLayout.height + clip: true + + ColumnLayout { + id: graphicsSettingsColumnLayout + anchors.left: parent.left + anchors.leftMargin: 26 + anchors.right: parent.right + anchors.rightMargin: 26 + anchors.top: parent.top + spacing: 8 + + ColumnLayout { + id: avatarNameTagsContainer + Layout.preferredWidth: parent.width + Layout.topMargin: 38 + spacing: 0 + + HifiStylesUit.RalewayRegular { + text: "GRAPHICS SETTINGS" + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: "#FFFFFF" + } + + ColumnLayout { + Layout.topMargin: 10 + Layout.preferredWidth: parent.width + spacing: 0 + + HifiControlsUit.RadioButton { + id: performanceLow + colorScheme: hifi.colorSchemes.dark + fontSize: 16 + leftPadding: 0 + text: "Low" + checked: Performance.getPerformancePreset() === PerformanceEnums.LOW + onClicked: { + Performance.setPerformancePreset(PerformanceEnums.LOW); + } + } + + HifiControlsUit.RadioButton { + id: performanceMedium + colorScheme: hifi.colorSchemes.dark + fontSize: 16 + leftPadding: 0 + text: "Medium" + checked: Performance.getPerformancePreset() === PerformanceEnums.MID + onClicked: { + Performance.setPerformancePreset(PerformanceEnums.MID); + } + } + + HifiControlsUit.RadioButton { + id: performanceHigh + colorScheme: hifi.colorSchemes.dark + fontSize: 16 + leftPadding: 0 + text: "High" + checked: Performance.getPerformancePreset() === PerformanceEnums.HIGH + onClicked: { + Performance.setPerformancePreset(PerformanceEnums.HIGH); + } + } + + HifiControlsUit.RadioButton { + id: performanceCustom + colorScheme: hifi.colorSchemes.dark + fontSize: 16 + leftPadding: 0 + text: "Custom" + checked: !(performanceLow.checked || performanceMedium.checked || performanceHigh.checked) + onClicked: { + + } + } + } + + ColumnLayout { + Layout.topMargin: 10 + Layout.preferredWidth: parent.width + spacing: 0 + + Item { + Layout.preferredWidth: parent.width + + HifiStylesUit.RalewayRegular { + id: resolutionHeader + text: "Resolution Scale (" + Number.parseFloat(Render.viewportResolutionScale).toPrecision(3) + ")" + anchors.left: parent.left + anchors.top: parent.top + width: 130 + height: paintedHeight + size: 16 + color: "#FFFFFF" + } + + HifiControlsUit.Slider { + id: resolutionScaleSlider + enabled: performanceCustom.checked + anchors.left: resolutionHeader.right + anchors.leftMargin: 57 + anchors.top: parent.top + width: 150 + height: resolutionHeader.height + colorScheme: hifi.colorSchemes.dark + minimumValue: 0.25 + maximumValue: 1.5 + stepSize: 0.02 + value: Render.viewportResolutionScale + live: true + + function updateResolutionScale(sliderValue) { + if (Render.viewportResolutionScale !== sliderValue) { + Render.viewportResolutionScale = sliderValue; + } + } + + onValueChanged: { + updateResolutionScale(value); + } + onPressedChanged: { + if (!pressed) { + updateResolutionScale(value); + } + } + } + } + } + } + } +} diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8bee8de8c3..4cf78c23ee 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -266,8 +266,13 @@ Menu::Menu() { // Settings > Graphics... action = addActionToQMenuAndActionHash(settingsMenu, "Graphics..."); connect(action, &QAction::triggered, [] { - qApp->showDialog(QString("hifi/dialogs/GraphicsPreferencesDialog.qml"), - QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog"); + auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); + auto hmd = DependencyManager::get(); + tablet->pushOntoStack("hifi/dialogs/graphics/GraphicsSettings.qml"); + + if (!hmd->getShouldShowTablet()) { + hmd->toggleShouldShowTablet(); + } }); // Settings > Security... From 73097113c7469d31948c3b1acf2d0af1cc8a6a94 Mon Sep 17 00:00:00 2001 From: amer cerkic Date: Wed, 10 Jul 2019 17:13:34 -0700 Subject: [PATCH 20/77] adding a null check to the display plugin. Possible that display plugin was disposed off during the check if hmdmode --- .../display-plugins/AbstractHMDScriptingInterface.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp index d068bef3b0..81e196e5ad 100644 --- a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp +++ b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp @@ -47,5 +47,12 @@ void AbstractHMDScriptingInterface::setIPDScale(float IPDScale) { } bool AbstractHMDScriptingInterface::isHMDMode() const { - return PluginContainer::getInstance().getActiveDisplayPlugin()->isHmd(); + + auto displayPlugin = PluginContainer::getInstance().getActiveDisplayPlugin(); + + if (displayPlugin) { + return displayPlugin->isHmd(); + } + + return false; } From d5d5741d42c5181c503ff7646409fd0de67b9923 Mon Sep 17 00:00:00 2001 From: amer cerkic Date: Wed, 10 Jul 2019 17:17:53 -0700 Subject: [PATCH 21/77] removed extra lines --- .../src/display-plugins/AbstractHMDScriptingInterface.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp index 81e196e5ad..4515a28997 100644 --- a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp +++ b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.cpp @@ -47,12 +47,9 @@ void AbstractHMDScriptingInterface::setIPDScale(float IPDScale) { } bool AbstractHMDScriptingInterface::isHMDMode() const { - auto displayPlugin = PluginContainer::getInstance().getActiveDisplayPlugin(); - if (displayPlugin) { return displayPlugin->isHmd(); } - return false; -} +} \ No newline at end of file From 645a99c200520789919562f9ebf1123b53b89afe Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 10 Jul 2019 17:36:25 -0700 Subject: [PATCH 22/77] Generate RSA key-pair early in start-up --- interface/src/Application.cpp | 11 +++++--- libraries/networking/src/AccountManager.cpp | 29 ++++++++++++++++----- libraries/networking/src/AccountManager.h | 3 +++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3c37bb6a6f..96350f5541 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1178,6 +1178,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } auto accountManager = DependencyManager::get(); + // set the account manager's root URL and trigger a login request if we don't have the access token + accountManager->setIsAgent(true); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); + if (!accountManager->hasKeyPair()) { + accountManager->generateNewUserKeypair(); + } + #ifndef Q_OS_ANDROID _logger->setSessionID(accountManager->getSessionID()); #endif @@ -1325,10 +1332,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo #endif connect(accountManager.data(), &AccountManager::usernameChanged, this, &Application::updateWindowTitle); - // set the account manager's root URL and trigger a login request if we don't have the access token - accountManager->setIsAgent(true); - accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); - // use our MyAvatar position and quat for address manager path addressManager->setPositionGetter([] { auto avatarManager = DependencyManager::get(); diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 96cfa66013..6cb1582dca 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -86,6 +86,7 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) : qRegisterMetaType("QHttpMultiPart*"); qRegisterMetaType(); + connect(this, &AccountManager::loginComplete, this, &AccountManager::uploadPublicKey); } const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash"; @@ -838,18 +839,30 @@ void AccountManager::generateNewKeypair(bool isUserKeypair, const QUuid& domainI connect(keypairGenerator, &RSAKeypairGenerator::errorGeneratingKeypair, this, &AccountManager::handleKeypairGenerationError); - qCDebug(networking) << "Starting worker thread to generate 2048-bit RSA keypair."; + static constexpr int RSA_THREAD_PRIORITY = 1; + qCDebug(networking) << "Starting worker thread to generate 2048-bit RSA keypair, priority" + << RSA_THREAD_PRIORITY << "- QThreadPool::maxThreadCount =" << QThreadPool::globalInstance()->maxThreadCount(); // Start on Qt's global thread pool. - QThreadPool::globalInstance()->start(keypairGenerator); + QThreadPool::globalInstance()->start(keypairGenerator, RSA_THREAD_PRIORITY); } } void AccountManager::processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey) { - qCDebug(networking) << "Generated 2048-bit RSA keypair. Uploading public key now."; + qCDebug(networking) << "Generated 2048-bit RSA keypair."; // hold the private key to later set our metaverse API account info if upload succeeds + _pendingPublicKey = publicKey; _pendingPrivateKey = privateKey; + uploadPublicKey(); +} + +void AccountManager::uploadPublicKey() { + if (_pendingPrivateKey.isEmpty()) { + return; + } + + qCDebug(networking) << "Attempting upload of public key"; // upload the public key so data-web has an up-to-date key const QString USER_PUBLIC_KEY_UPDATE_PATH = "api/v1/user/public_key"; @@ -871,7 +884,7 @@ void AccountManager::processGeneratedKeypair(QByteArray publicKey, QByteArray pr publicKeyPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"public_key\"; filename=\"public_key\"")); - publicKeyPart.setBody(publicKey); + publicKeyPart.setBody(_pendingPublicKey); requestMultiPart->append(publicKeyPart); // Currently broken? We don't have the temporary domain key. @@ -900,6 +913,7 @@ void AccountManager::publicKeyUploadSucceeded(QNetworkReply* reply) { // public key upload complete - store the matching private key and persist the account to settings _accountInfo.setPrivateKey(_pendingPrivateKey); + _pendingPublicKey.clear(); _pendingPrivateKey.clear(); persistAccountToFile(); @@ -915,9 +929,6 @@ void AccountManager::publicKeyUploadFailed(QNetworkReply* reply) { // we aren't waiting for a response any longer _isWaitingForKeypairResponse = false; - - // clear our pending private key - _pendingPrivateKey.clear(); } void AccountManager::handleKeypairGenerationError() { @@ -961,3 +972,7 @@ void AccountManager::saveLoginStatus(bool isLoggedIn) { } } } + +bool AccountManager::hasKeyPair() const { + return _accountInfo.hasPrivateKey(); +} diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index c2187f79cb..a88a5cc4e7 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -81,6 +81,7 @@ public: bool needsToRefreshToken(); Q_INVOKABLE bool checkAndSignalForAccessToken(); void setAccessTokenForCurrentAuthURL(const QString& accessToken); + bool hasKeyPair() const; void requestProfile(); @@ -139,6 +140,7 @@ signals: private slots: void handleKeypairGenerationError(); void processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey); + void uploadPublicKey(); void publicKeyUploadSucceeded(QNetworkReply* reply); void publicKeyUploadFailed(QNetworkReply* reply); void generateNewKeypair(bool isUserKeypair = true, const QUuid& domainID = QUuid()); @@ -162,6 +164,7 @@ private: bool _isWaitingForKeypairResponse { false }; QByteArray _pendingPrivateKey; + QByteArray _pendingPublicKey; QUuid _sessionID { QUuid::createUuid() }; From c4a0b39068f7c0666be1c1ed6859e0c64c8afb2c Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Wed, 10 Jul 2019 17:56:54 -0700 Subject: [PATCH 23/77] requested changes --- interface/src/ui/InteractiveWindow.cpp | 30 +++++++++++++++++--------- interface/src/ui/InteractiveWindow.h | 23 ++++++++++++++++++++ 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index c85d7bc301..84094a2500 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -51,6 +51,26 @@ static const QStringList KNOWN_SCHEMES = QStringList() << "http" << "https" << " static const int DEFAULT_HEIGHT = 60; +QmlWindowProxy::QmlWindowProxy(QObject* qmlObject, QObject* parent) : QmlWrapper(qmlObject, parent) { + _qmlWindow = qmlObject; +} + +void QmlWindowProxy::updateInteractiveWindowPositionForMode() { +} + +void QmlWindowProxy::setPosition(const glm::vec2& position) { +} + +glm::vec2 QmlWindowProxy::getPosition() const { +} + +void QmlWindowProxy::setSize(const glm::vec2& size) { +} + +glm::vec2 QmlWindowProxy::getSize() const { +} + +void QmlWindowProxy::setTitle(const QString& title static void dockWidgetDeleter(DockWidget* dockWidget) { dockWidget->deleteLater(); } @@ -296,11 +316,6 @@ void InteractiveWindow::qmlToScript(const QVariant& message) { } void InteractiveWindow::setVisible(bool visible) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setVisible", Q_ARG(bool, visible)); - return; - } - if (!_qmlWindow.isNull()) { QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_VISIBLE_PROPERTY), Q_ARG(bool, visible)); @@ -324,11 +339,6 @@ glm::vec2 InteractiveWindow::getPosition() const { } void InteractiveWindow::setPosition(const glm::vec2& position) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setPosition", Q_ARG(const glm::vec2&, position)); - return; - } - if (!_qmlWindow.isNull()) { QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_POSITION_PROPERTY), Q_ARG(QPointF, QPointF(position.x, position.y))); diff --git a/interface/src/ui/InteractiveWindow.h b/interface/src/ui/InteractiveWindow.h index c7b3631dde..d9886bd138 100644 --- a/interface/src/ui/InteractiveWindow.h +++ b/interface/src/ui/InteractiveWindow.h @@ -18,10 +18,33 @@ #include #include #include +#include #include #include +class QmlWindowProxy : QmlWrapper { + Q_OBJECT + +public: + QmlWindowProxy(QObject* qmlObject, QObject* parent = nullptr); + + Q_INVOKABLE void updateInteractiveWindowPositionForMode(); + + Q_INVOKABLE void setPosition(const glm::vec2& position); + glm::vec2 getPositiion() const; + + Q_INVOKABLE void setSize(const glm::vec2& size); + glm::vec2 getSize() const; + + Q_INVOKABLE void setTitle(const QString& title); + QString getTitle() const; +private: + QObject* _qmlWindow; + +}; + + namespace InteractiveWindowEnums { Q_NAMESPACE From d545ba5bc6543e575064e9b700873465d21acdbd Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 10 Jul 2019 18:32:43 -0700 Subject: [PATCH 24/77] haze on most entities, working on skybox --- cmake/macros/AutoScribeShader.cmake | 9 +- interface/src/graphics/GraphicsEngine.cpp | 2 +- .../RenderableParticleEffectEntityItem.cpp | 2 +- .../src/RenderablePolyVoxEntityItem.cpp | 75 ++++++++--------- .../entities-renderer/src/paintStroke.slf | 2 +- libraries/entities-renderer/src/polyvox.slf | 8 +- libraries/graphics/src/graphics/Haze.cpp | 2 +- .../src => graphics/src/graphics}/Haze.slh | 5 +- .../graphics/src/graphics/ShaderConstants.h | 5 +- libraries/graphics/src/graphics/Skybox.cpp | 32 +++---- libraries/graphics/src/graphics/Skybox.h | 4 +- libraries/graphics/src/graphics/skybox.slf | 12 ++- libraries/graphics/src/graphics/skybox.slp | 1 + libraries/graphics/src/graphics/skybox.slv | 4 +- .../src/procedural/ProceduralSkybox.cpp | 9 +- .../src/procedural/ProceduralSkybox.h | 4 +- .../render-utils/src/BackgroundStage.cpp | 17 +++- libraries/render-utils/src/BackgroundStage.h | 3 +- .../src/DeferredLightingEffect.cpp | 3 +- libraries/render-utils/src/DrawHaze.cpp | 2 +- libraries/render-utils/src/GlobalLight.slh | 84 +++++++++++++------ libraries/render-utils/src/Haze.slf | 2 +- .../render-utils/src/RenderCommonTask.cpp | 14 +++- libraries/render-utils/src/RenderCommonTask.h | 5 +- .../render-utils/src/RenderDeferredTask.cpp | 10 +-- .../render-utils/src/RenderForwardTask.cpp | 25 ++++-- .../render-utils/src/RenderForwardTask.h | 2 +- .../render-utils/src/RenderHUDLayerTask.cpp | 5 +- .../render-utils/src/RenderHUDLayerTask.h | 4 +- .../src/directional_skybox_light.slf | 2 +- .../src/directional_skybox_light_shadow.slf | 2 +- libraries/render-utils/src/model.slf | 9 +- .../src/render-utils/ShaderConstants.h | 2 - libraries/render-utils/src/sdf_text3D.slf | 32 +++---- libraries/render-utils/src/simple.slf | 34 ++++---- libraries/render-utils/src/web_browser.slf | 4 +- libraries/render-utils/src/web_browser.slv | 7 +- libraries/render/src/render/ShapePipeline.cpp | 4 +- libraries/render/src/render/ShapePipeline.h | 2 +- 39 files changed, 268 insertions(+), 182 deletions(-) rename libraries/{render-utils/src => graphics/src/graphics}/Haze.slh (97%) diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake index f5a497962c..63f7c0c7d6 100755 --- a/cmake/macros/AutoScribeShader.cmake +++ b/cmake/macros/AutoScribeShader.cmake @@ -268,6 +268,7 @@ macro(AUTOSCRIBE_SHADER_LIB) set(PROGRAM_ENUMS "namespace program { enum {\n") foreach(PROGRAM_FILE ${SHADER_PROGRAM_FILES}) get_filename_component(PROGRAM_NAME ${PROGRAM_FILE} NAME_WE) + get_filename_component(PROGRAM_FOLDER ${PROGRAM_FILE} DIRECTORY) file(READ ${PROGRAM_FILE} PROGRAM_CONFIG) set(AUTOSCRIBE_PROGRAM_VERTEX ${PROGRAM_NAME}) set(AUTOSCRIBE_PROGRAM_FRAGMENT ${PROGRAM_NAME}) @@ -315,7 +316,9 @@ macro(AUTOSCRIBE_SHADER_LIB) if (HAS_FRAGMENT EQUAL -1) set(DEFINES "${VERTEX_DEFINES}") set(SHADER_LIST "") - set(SHADER_FILE "${SRC_FOLDER}/${VERTEX_NAME}.slv") + unset(SHADER_FILE) + unset(SHADER_FILE CACHE) + find_file(SHADER_FILE "${VERTEX_NAME}.slv" PATHS "${PROGRAM_FOLDER}" PATH_SUFFIXES "..") AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) string(CONCAT VERTEX_ENUMS "${VERTEX_ENUMS}" "${SHADER_LIST}") else() @@ -331,7 +334,9 @@ macro(AUTOSCRIBE_SHADER_LIB) if (HAS_VERTEX EQUAL -1) set(DEFINES "${FRAGMENT_DEFINES}") set(SHADER_LIST "") - set(SHADER_FILE "${SRC_FOLDER}/${FRAGMENT_NAME}.slf") + unset(SHADER_FILE) + unset(SHADER_FILE CACHE) + find_file(SHADER_FILE "${FRAGMENT_NAME}.slf" PATHS "${PROGRAM_FOLDER}" PATH_SUFFIXES "..") AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) string(CONCAT FRAGMENT_ENUMS "${FRAGMENT_ENUMS}" "${SHADER_LIST}") else() diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index 7f9a612697..284118a52a 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -259,7 +259,7 @@ void GraphicsEngine::render_performFrame() { batch.enableSkybox(true); batch.enableStereo(isStereo); batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); - _splashScreen->render(batch, viewFrustum); + _splashScreen->render(batch, viewFrustum, renderArgs._renderMethod == RenderArgs::RenderMethod::FORWARD); }); } else { { diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index d517ecd026..36f8ccf8f6 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -23,7 +23,7 @@ static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; static std::weak_ptr _texturedPipeline; -static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) { +static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) { auto texturedPipeline = _texturedPipeline.lock(); if (!texturedPipeline) { auto state = std::make_shared(); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index adf0a2d162..3adeecabcc 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -34,9 +34,7 @@ #include "EntityTreeRenderer.h" -#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT -# include -#endif +#include #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -1553,52 +1551,49 @@ using namespace render; using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER; -static gpu::PipelinePointer _pipelines[2]; -static gpu::PipelinePointer _wireframePipelines[2]; +static std::map, ShapePipelinePointer> _pipelines; static gpu::Stream::FormatPointer _vertexFormat; -ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) { - if (!_pipelines[0]) { +ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) { + // FIXME: custom pipelines like this don't handle shadows or renderLayers correctly + + if (_pipelines.empty()) { using namespace shader::entities_renderer::program; - int programsIds[2] = { polyvox, polyvox_fade }; - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - PrepareStencil::testMaskDrawShape(*state); + static const std::vector> keys = { + std::make_tuple(false, false, polyvox), std::make_tuple(true, false, polyvox_forward) +#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT + , std::make_tuple(false, true, polyvox_fade), std::make_tuple(true, true, polyvox_forward_fade) +#else + , std::make_tuple(false, true, polyvox), std::make_tuple(true, true, polyvox_forward) +#endif + }; + for (auto& key : keys) { + for (int i = 0; i < 2; ++i) { + bool wireframe = i != 0; - auto wireframeState = std::make_shared(); - wireframeState->setCullMode(gpu::State::CULL_BACK); - wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL); - wireframeState->setFillMode(gpu::State::FILL_LINE); - PrepareStencil::testMaskDrawShape(*wireframeState); + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_BACK); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + PrepareStencil::testMaskDrawShape(*state); - // Two sets of pipelines: normal and fading - for (auto i = 0; i < 2; i++) { - gpu::ShaderPointer program = gpu::Shader::createProgram(programsIds[i]); - _pipelines[i] = gpu::Pipeline::create(program, state); - _wireframePipelines[i] = gpu::Pipeline::create(program, wireframeState); + if (wireframe) { + state->setFillMode(gpu::State::FILL_LINE); + } + + auto pipeline = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state); + if (std::get<1>(key)) { + _pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared(pipeline, nullptr, nullptr, nullptr); + } else { + const auto& fadeEffect = DependencyManager::get(); + _pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared(pipeline, nullptr, + fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); + } + } } } -#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT - if (key.isFaded()) { - const auto& fadeEffect = DependencyManager::get(); - if (key.isWireframe()) { - return std::make_shared(_wireframePipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); - } else { - return std::make_shared(_pipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); - } - } else { -#endif - if (key.isWireframe()) { - return std::make_shared(_wireframePipelines[0], nullptr, nullptr, nullptr); - } else { - return std::make_shared(_pipelines[0], nullptr, nullptr, nullptr); - } -#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT - } -#endif + return _pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, key.isFaded(), key.isWireframe())]; } PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 045c5bd088..837291efe6 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -22,7 +22,7 @@ LAYOUT(binding=0) uniform sampler2D _texture; <@if not HIFI_USE_FORWARD@> -layout(location=0) in vec3 _normalWS; + layout(location=0) in vec3 _normalWS; <@endif@> layout(location=1) in vec2 _texCoord; layout(location=2) in vec4 _color; diff --git a/libraries/entities-renderer/src/polyvox.slf b/libraries/entities-renderer/src/polyvox.slf index 37cc7bcbbc..f08728dbcb 100644 --- a/libraries/entities-renderer/src/polyvox.slf +++ b/libraries/entities-renderer/src/polyvox.slf @@ -28,7 +28,7 @@ <@include DefaultMaterials.slh@> <@include GlobalLight.slh@> - <$declareEvalSkyboxGlobalColor()$> + <$declareEvalSkyboxGlobalColor(_SCRIBE_NULL, HIFI_USE_FORWARD)$> <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> @@ -52,7 +52,9 @@ LAYOUT(binding=0) uniform polyvoxParamsBuffer { PolyvoxParams params; }; -<@else@> +<@endif@> + +<@if HIFI_USE_SHADOW or HIFI_USE_FORWARD@> layout(location=0) out vec4 _fragColor0; <@endif@> @@ -101,7 +103,7 @@ void main(void) { DEFAULT_SCATTERING); <@else@> TransformCamera cam = getTransformCamera(); - vec4 color = vec4(evalSkyboxGlobalColor( + _fragColor0 = vec4(evalSkyboxGlobalColor( cam._viewInverse, 1.0, DEFAULT_OCCLUSION, diff --git a/libraries/graphics/src/graphics/Haze.cpp b/libraries/graphics/src/graphics/Haze.cpp index d9bee7507f..9e3cc15c57 100644 --- a/libraries/graphics/src/graphics/Haze.cpp +++ b/libraries/graphics/src/graphics/Haze.cpp @@ -98,7 +98,7 @@ void Haze::setHazeGlareColor(const glm::vec3 hazeGlareColor) { void Haze::setHazeActive(const bool isHazeActive) { auto& params = _hazeParametersBuffer.get(); - if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE )&& !isHazeActive) { + if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) && !isHazeActive) { _hazeParametersBuffer.edit().hazeMode &= ~HAZE_MODE_IS_ACTIVE; } else if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) != HAZE_MODE_IS_ACTIVE) && isHazeActive) { _hazeParametersBuffer.edit().hazeMode |= HAZE_MODE_IS_ACTIVE; diff --git a/libraries/render-utils/src/Haze.slh b/libraries/graphics/src/graphics/Haze.slh similarity index 97% rename from libraries/render-utils/src/Haze.slh rename to libraries/graphics/src/graphics/Haze.slh index e2285febe4..a2d8bb0523 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/graphics/src/graphics/Haze.slh @@ -10,7 +10,7 @@ <@if not HAZE_SLH@> <@def HAZE_SLH@> -<@include render-utils/ShaderConstants.h@> +<@include graphics/ShaderConstants.h@> const int HAZE_MODE_IS_ACTIVE = 1 << 0; const int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1; @@ -38,8 +38,7 @@ struct HazeParams { float hazeKeyLightAltitudeFactor; }; -// See ShapePipeline::Slot::BUFFER in ShapePipeline.h -LAYOUT_STD140(binding=RENDER_UTILS_BUFFER_HAZE_PARAMS) uniform hazeBuffer { +LAYOUT_STD140(binding=GRAPHICS_BUFFER_HAZE_PARAMS) uniform hazeBuffer { HazeParams hazeParams; }; diff --git a/libraries/graphics/src/graphics/ShaderConstants.h b/libraries/graphics/src/graphics/ShaderConstants.h index 0aff0a7077..3a614d26cd 100644 --- a/libraries/graphics/src/graphics/ShaderConstants.h +++ b/libraries/graphics/src/graphics/ShaderConstants.h @@ -32,6 +32,8 @@ #define GRAPHICS_TEXTURE_SKYBOX 11 #define GRAPHICS_BUFFER_SKYBOX_PARAMS 5 +#define GRAPHICS_BUFFER_HAZE_PARAMS 7 + // (); +static std::map _pipelines; + +void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox, bool forward) { + if (_pipelines.empty()) { + static const std::vector> keys = { + std::make_tuple(false, shader::graphics::program::skybox), + std::make_tuple(true, shader::graphics::program::skybox_forward) + }; + for (auto& key : keys) { + auto state = std::make_shared(); // Must match PrepareStencil::STENCIL_BACKGROUND const int8_t STENCIL_BACKGROUND = 0; - skyState->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_BACKGROUND, 0xFF, gpu::EQUAL, + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_BACKGROUND, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); - thePipeline = gpu::Pipeline::create(skyShader, skyState); + _pipelines[std::get<0>(key)] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<1>(key)), state); } - }); - + } // Render glm::mat4 projMat; @@ -111,7 +111,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky batch.setViewTransform(viewTransform); batch.setModelTransform(Transform()); // only for Mac - batch.setPipeline(thePipeline); + batch.setPipeline(_pipelines[forward]); skybox.prepare(batch); batch.draw(gpu::TRIANGLE_STRIP, 4); diff --git a/libraries/graphics/src/graphics/Skybox.h b/libraries/graphics/src/graphics/Skybox.h index 50189f4c51..5668604c8b 100755 --- a/libraries/graphics/src/graphics/Skybox.h +++ b/libraries/graphics/src/graphics/Skybox.h @@ -44,9 +44,9 @@ public: virtual void clear(); void prepare(gpu::Batch& batch) const; - virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const; + virtual void render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const; - static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox); + static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox, bool forward); const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; } diff --git a/libraries/graphics/src/graphics/skybox.slf b/libraries/graphics/src/graphics/skybox.slf index 801fc33c28..0dea1d7882 100755 --- a/libraries/graphics/src/graphics/skybox.slf +++ b/libraries/graphics/src/graphics/skybox.slf @@ -1,8 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> -// skybox.frag -// fragment shader // // Created by Sam Gateau on 5/5/2015. // Copyright 2015 High Fidelity, Inc. @@ -12,6 +11,10 @@ // <@include graphics/ShaderConstants.h@> +<@if HIFI_USE_FORWARD@> + <@include graphics/Haze.slh@> +<@endif@> + LAYOUT(binding=GRAPHICS_TEXTURE_SKYBOX) uniform samplerCube cubeMap; struct Skybox { @@ -36,4 +39,9 @@ void main(void) { vec3 skyboxColor = skybox.color.rgb; _fragColor = vec4(mix(vec3(1.0), skyboxTexel, float(skybox.color.a > 0.0)) * mix(vec3(1.0), skyboxColor, float(skybox.color.a < 1.0)), 1.0); + +<@if HIFI_USE_FORWARD@> + _fragColor = vec4(hazeParams.hazeColor, 1); +<@endif@> + } diff --git a/libraries/graphics/src/graphics/skybox.slp b/libraries/graphics/src/graphics/skybox.slp index e69de29bb2..e9908ffd1b 100644 --- a/libraries/graphics/src/graphics/skybox.slp +++ b/libraries/graphics/src/graphics/skybox.slp @@ -0,0 +1 @@ +DEFINES forward:f \ No newline at end of file diff --git a/libraries/graphics/src/graphics/skybox.slv b/libraries/graphics/src/graphics/skybox.slv index 4b14872df2..a6e6930d22 100755 --- a/libraries/graphics/src/graphics/skybox.slv +++ b/libraries/graphics/src/graphics/skybox.slv @@ -1,8 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> -// skybox.vert -// vertex shader // // Created by Sam Gateau on 5/5/2015. // Copyright 2015 High Fidelity, Inc. @@ -12,7 +11,6 @@ // <@include gpu/Transform.slh@> - <$declareStandardTransform()$> layout(location=0) out vec3 _normal; diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 53df1532dc..5e8c6f4865 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -18,6 +18,7 @@ #include ProceduralSkybox::ProceduralSkybox(uint64_t created) : graphics::Skybox(), _created(created) { + // FIXME: support forward rendering for procedural skyboxes (needs haze calculation) _procedural._vertexSource = gpu::Shader::createVertex(shader::graphics::vertex::skybox)->getSource(); _procedural._opaqueFragmentSource = shader::Source::get(shader::procedural::fragment::proceduralSkybox); // Adjust the pipeline state for background using the stencil test @@ -40,15 +41,15 @@ void ProceduralSkybox::clear() { Skybox::clear(); } -void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const { +void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const { if (_procedural.isReady()) { - ProceduralSkybox::render(batch, frustum, (*this)); + ProceduralSkybox::render(batch, frustum, (*this), forward); } else { - Skybox::render(batch, frustum); + Skybox::render(batch, frustum, forward); } } -void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox) { +void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox, bool forward) { glm::mat4 projMat; viewFrustum.evalProjectionMatrix(projMat); diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.h b/libraries/procedural/src/procedural/ProceduralSkybox.h index a1d7ea8fa7..983b432089 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.h +++ b/libraries/procedural/src/procedural/ProceduralSkybox.h @@ -26,8 +26,8 @@ public: bool empty() override; void clear() override; - void render(gpu::Batch& batch, const ViewFrustum& frustum) const override; - static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox); + void render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const override; + static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox, bool forward); uint64_t getCreated() const { return _created; } diff --git a/libraries/render-utils/src/BackgroundStage.cpp b/libraries/render-utils/src/BackgroundStage.cpp index ca643b9f14..91b766d90b 100644 --- a/libraries/render-utils/src/BackgroundStage.cpp +++ b/libraries/render-utils/src/BackgroundStage.cpp @@ -13,6 +13,8 @@ #include +#include + std::string BackgroundStage::_stageName { "BACKGROUND_STAGE"}; const BackgroundStage::Index BackgroundStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX }; @@ -71,6 +73,8 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, } } + const auto& hazeFrame = inputs.get2(); + if (skybox && !skybox->empty()) { PerformanceTimer perfTimer("skybox"); auto args = renderContext->args; @@ -91,7 +95,18 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - skybox->render(batch, args->getViewFrustum()); + // If we're using forward rendering, we need to calculate haze + if (args->_renderMethod == render::Args::RenderMethod::FORWARD) { + const auto& hazeStage = args->_scene->getStage(); + if (hazeStage && hazeFrame->_hazes.size() > 0) { + const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front()); + if (hazePointer) { + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer()); + } + } + } + + skybox->render(batch, args->getViewFrustum(), args->_renderMethod == render::Args::RenderMethod::FORWARD); }); args->_batch = nullptr; } diff --git a/libraries/render-utils/src/BackgroundStage.h b/libraries/render-utils/src/BackgroundStage.h index 61ca576ca8..3015b721b1 100644 --- a/libraries/render-utils/src/BackgroundStage.h +++ b/libraries/render-utils/src/BackgroundStage.h @@ -16,6 +16,7 @@ #include #include #include +#include "HazeStage.h" #include "LightingModel.h" @@ -81,7 +82,7 @@ public: class DrawBackgroundStage { public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet3; using JobModel = render::Job::ModelI; DrawBackgroundStage() {} diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 3ab9340906..3b7c66d42d 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -432,7 +432,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, if (hazeStage && hazeFrame->_hazes.size() > 0) { const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front()); if (hazePointer) { - batch.setUniformBuffer(ru::Buffer::HazeParams, hazePointer->getHazeParametersBuffer()); + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer()); } } @@ -655,7 +655,6 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) { if (!_defaultHaze) { auto hazeStage = renderContext->_scene->getStage(); if (hazeStage) { - auto haze = std::make_shared(); _defaultHaze = haze; diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index db80cbecae..f7be5160b6 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -78,7 +78,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(outputFramebufferSize, args->_viewport)); batch.setPipeline(_hazePipeline); - batch.setUniformBuffer(ru::Buffer::HazeParams, haze->getHazeParametersBuffer()); + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, haze->getHazeParametersBuffer()); batch.setUniformBuffer(ru::Buffer::DeferredFrameTransform, transformBuffer->getFrameTransformBuffer()); batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer()); diff --git a/libraries/render-utils/src/GlobalLight.slh b/libraries/render-utils/src/GlobalLight.slh index 1c8914adf3..6702270a5a 100644 --- a/libraries/render-utils/src/GlobalLight.slh +++ b/libraries/render-utils/src/GlobalLight.slh @@ -98,9 +98,9 @@ vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, floa <@endfunc@> -<@include Haze.slh@> +<@include graphics/Haze.slh@> -<@func declareEvalSkyboxGlobalColor(supportScattering)@> +<@func declareEvalSkyboxGlobalColor(supportScattering, computeHaze)@> <$declareLightingAmbient(_SCRIBE_NULL, 1, _SCRIBE_NULL, $supportScattering$)$> <$declareLightingDirectional($supportScattering$)$> @@ -109,13 +109,13 @@ vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, floa <$declareDeferredCurvature()$> <@endif@> -vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, +vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, vec3 albedo, vec3 fresnel, float metallic, float roughness <@if supportScattering@> , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature <@endif@> ) { - <$prepareGlobalLight(position, normal)$> + <$prepareGlobalLight(positionES, normalWS)$> SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); @@ -130,6 +130,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu color += ambientDiffuse; color += ambientSpecular; + // Directional vec3 directionalDiffuse; vec3 directionalSpecular; evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation @@ -140,9 +141,24 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu color += directionalDiffuse; color += directionalSpecular; - // Attenuate the light if haze effect selected - if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { - color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); + // Haze + if (isHazeEnabled() > 0.0) { + if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { + color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); + } + +<@if computeHaze@> + if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + vec4 hazeColor = computeHazeColor( + positionES, // fragment position in eye coordinates + fragPositionWS, // fragment position in world coordinates + invViewMat[3].xyz, // eye position in world coordinates + lightDirection // keylight direction vector in world coordinates + ); + + color = mix(color.rgb, hazeColor.rgb, hazeColor.a); + } +<@endif@> } return color; @@ -181,8 +197,8 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur <$declareLightingDirectional()$> vec3 evalGlobalLightingAlphaBlended( - mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, - vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) + mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, + vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) { <$prepareGlobalLight(positionES, normalWS)$> @@ -204,23 +220,29 @@ vec3 evalGlobalLightingAlphaBlended( color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); // Haze - if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { - vec4 hazeColor = computeHazeColor( - positionES, // fragment position in eye coordinates - fragPositionWS, // fragment position in world coordinates - invViewMat[3].xyz, // eye position in world coordinates - lightDirection // keylight direction vector in world coordinates - ); + if (isHazeEnabled() > 0.0) { + if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { + color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); + } - color = mix(color.rgb, hazeColor.rgb, hazeColor.a); + if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + vec4 hazeColor = computeHazeColor( + positionES, // fragment position in eye coordinates + fragPositionWS, // fragment position in world coordinates + invViewMat[3].xyz, // eye position in world coordinates + lightDirection // keylight direction vector in world coordinates + ); + + color = mix(color.rgb, hazeColor.rgb, hazeColor.a); + } } return color; } vec3 evalGlobalLightingAlphaBlended( - mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, - vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) + mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, + vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) { <$fetchGlobalLight()$> @@ -241,15 +263,23 @@ vec3 evalGlobalLightingAlphaBlended( color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); // Haze - if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { - vec4 hazeColor = computeHazeColor( - positionES, // fragment position in eye coordinates - positionWS, // fragment position in world coordinates - invViewMat[3].xyz, // eye position in world coordinates - lightDirection // keylight direction vector - ); + if (isHazeEnabled() > 0.0) { + vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0)); - color = mix(color.rgb, hazeColor.rgb, hazeColor.a); + if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { + color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); + } + + if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + vec4 hazeColor = computeHazeColor( + positionES, // fragment position in eye coordinates + fragPositionWS, // fragment position in world coordinates + invViewMat[3].xyz, // eye position in world coordinates + lightDirection // keylight direction vector in world coordinates + ); + + color = mix(color.rgb, hazeColor.rgb, hazeColor.a); + } } return color; diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index 170e69eb2d..951841ad49 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -19,7 +19,7 @@ <@include LightingModel.slh@> <$declareLightBuffer()$> -<@include Haze.slh@> +<@include graphics/Haze.slh@> LAYOUT(binding=RENDER_UTILS_TEXTURE_HAZE_LINEAR_DEPTH) uniform sampler2D linearDepthMap; diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index 54e43abc07..9ea4ac9f3c 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -59,13 +59,21 @@ void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs& const auto& inItems = inputs.get0(); const auto& lightingModel = inputs.get1(); - const auto jitter = inputs.get2(); + const auto& hazeFrame = inputs.get2(); + const auto jitter = inputs.get3(); config->setNumDrawn((int)inItems.size()); emit config->numDrawnChanged(); RenderArgs* args = renderContext->args; + graphics::HazePointer haze; + const auto& hazeStage = renderContext->args->_scene->getStage(); + if (hazeStage && hazeFrame->_hazes.size() > 0) { + // We use _hazes.back() here because the last haze object will always have haze disabled. + haze = hazeStage->getHaze(hazeFrame->_hazes.back()); + } + // Clear the framebuffer without stereo // Needs to be distinct from the other batch because using the clear call // while stereo is enabled triggers a warning @@ -96,6 +104,10 @@ void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs& batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer()); batch.setResourceTexture(ru::Texture::AmbientFresnel, lightingModel->getAmbientFresnelLUT()); + if (haze) { + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, haze->getHazeParametersBuffer()); + } + if (_opaquePass) { renderStateSortShapes(renderContext, _shapePlumber, inItems, _maxDrawn); } else { diff --git a/libraries/render-utils/src/RenderCommonTask.h b/libraries/render-utils/src/RenderCommonTask.h index 756445a30f..ec50fbf2cc 100644 --- a/libraries/render-utils/src/RenderCommonTask.h +++ b/libraries/render-utils/src/RenderCommonTask.h @@ -11,10 +11,9 @@ #include #include "LightStage.h" +#include "HazeStage.h" #include "LightingModel.h" - - class BeginGPURangeTimer { public: using JobModel = render::Job::ModelO; @@ -62,7 +61,7 @@ protected: class DrawLayered3D { public: - using Inputs = render::VaryingSet3; + using Inputs = render::VaryingSet4; using Config = DrawLayered3DConfig; using JobModel = render::Job::ModelI; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index e513fb7282..c26f3b613c 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -207,7 +207,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("RenderDeferred", deferredLightingInputs); // Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job - const auto backgroundInputs = DrawBackgroundStage::Inputs(lightingModel, backgroundFrame).asVarying(); + const auto backgroundInputs = DrawBackgroundStage::Inputs(lightingModel, backgroundFrame, hazeFrame).asVarying(); task.addJob("DrawBackgroundDeferred", backgroundInputs); const auto drawHazeInputs = render::Varying(DrawHaze::Inputs(hazeFrame, lightingFramebuffer, linearDepthTarget, deferredFrameTransform, lightingModel, lightFrame)); @@ -225,8 +225,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("HighlightRangeTimer", outlineRangeTimer); // Layered Over (in front) - const auto inFrontOpaquesInputs = DrawLayered3D::Inputs(inFrontOpaque, lightingModel, jitter).asVarying(); - const auto inFrontTransparentsInputs = DrawLayered3D::Inputs(inFrontTransparent, lightingModel, jitter).asVarying(); + const auto inFrontOpaquesInputs = DrawLayered3D::Inputs(inFrontOpaque, lightingModel, hazeFrame, jitter).asVarying(); + const auto inFrontTransparentsInputs = DrawLayered3D::Inputs(inFrontTransparent, lightingModel, hazeFrame, jitter).asVarying(); task.addJob("DrawInFrontOpaque", inFrontOpaquesInputs, true); task.addJob("DrawInFrontTransparent", inFrontTransparentsInputs, false); @@ -254,7 +254,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", toneMappedBuffer); // HUD Layer - const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying(); + const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent, hazeFrame).asVarying(); task.addJob("RenderHUDLayer", renderHUDLayerInputs); } @@ -506,7 +506,7 @@ void RenderTransparentDeferred::run(const RenderContextPointer& renderContext, c if (hazeStage && hazeFrame->_hazes.size() > 0) { const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front()); if (hazePointer) { - batch.setUniformBuffer(ru::Buffer::HazeParams, hazePointer->getHazeParametersBuffer()); + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer()); } } diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index ef3dcee15f..b6b17ee376 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -90,6 +90,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend const auto currentStageFrames = lightingStageInputs.get0(); const auto lightFrame = currentStageFrames[0]; const auto backgroundFrame = currentStageFrames[1]; + const auto hazeFrame = currentStageFrames[2]; const auto& zones = lightingStageInputs[1]; @@ -111,21 +112,21 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend task.addJob("PrepareStencil", scaledPrimaryFramebuffer); // Draw opaques forward - const auto opaqueInputs = DrawForward::Inputs(opaques, lightingModel).asVarying(); + const auto opaqueInputs = DrawForward::Inputs(opaques, lightingModel, hazeFrame).asVarying(); task.addJob("DrawOpaques", opaqueInputs, shapePlumber, true); // Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job - const auto backgroundInputs = DrawBackgroundStage::Inputs(lightingModel, backgroundFrame).asVarying(); + const auto backgroundInputs = DrawBackgroundStage::Inputs(lightingModel, backgroundFrame, hazeFrame).asVarying(); task.addJob("DrawBackgroundForward", backgroundInputs); // Draw transparent objects forward - const auto transparentInputs = DrawForward::Inputs(transparents, lightingModel).asVarying(); + const auto transparentInputs = DrawForward::Inputs(transparents, lightingModel, hazeFrame).asVarying(); task.addJob("DrawTransparents", transparentInputs, shapePlumber, false); // Layered const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); - const auto inFrontOpaquesInputs = DrawLayered3D::Inputs(inFrontOpaque, lightingModel, nullJitter).asVarying(); - const auto inFrontTransparentsInputs = DrawLayered3D::Inputs(inFrontTransparent, lightingModel, nullJitter).asVarying(); + const auto inFrontOpaquesInputs = DrawLayered3D::Inputs(inFrontOpaque, lightingModel, hazeFrame, nullJitter).asVarying(); + const auto inFrontTransparentsInputs = DrawLayered3D::Inputs(inFrontTransparent, lightingModel, hazeFrame, nullJitter).asVarying(); task.addJob("DrawInFrontOpaque", inFrontOpaquesInputs, true); task.addJob("DrawInFrontTransparent", inFrontTransparentsInputs, false); @@ -167,7 +168,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", toneMappedBuffer); // HUD Layer - const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying(); + const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent, hazeFrame).asVarying(); task.addJob("RenderHUDLayer", renderHUDLayerInputs); } @@ -258,11 +259,17 @@ void DrawForward::run(const RenderContextPointer& renderContext, const Inputs& i const auto& inItems = inputs.get0(); const auto& lightingModel = inputs.get1(); + const auto& hazeFrame = inputs.get2(); + + graphics::HazePointer haze; + const auto& hazeStage = renderContext->args->_scene->getStage(); + if (hazeStage && hazeFrame->_hazes.size() > 0) { + haze = hazeStage->getHaze(hazeFrame->_hazes.front()); + } gpu::doInBatch("DrawForward::run", args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; - // Setup projection glm::mat4 projMat; Transform viewMat; @@ -276,6 +283,10 @@ void DrawForward::run(const RenderContextPointer& renderContext, const Inputs& i batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer()); batch.setResourceTexture(ru::Texture::AmbientFresnel, lightingModel->getAmbientFresnelLUT()); + if (haze) { + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, haze->getHazeParametersBuffer()); + } + // From the lighting model define a global shapeKey ORED with individiual keys ShapeKey::Builder keyBuilder; if (lightingModel->isWireframeEnabled()) { diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index baf7f66c6c..2abf248692 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -96,7 +96,7 @@ private: class DrawForward{ public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet3; using JobModel = render::Job::ModelI; DrawForward(const render::ShapePlumberPointer& shapePlumber, bool opaquePass) : _shapePlumber(shapePlumber), _opaquePass(opaquePass) {} diff --git a/libraries/render-utils/src/RenderHUDLayerTask.cpp b/libraries/render-utils/src/RenderHUDLayerTask.cpp index 840d9e8002..743e59eebc 100644 --- a/libraries/render-utils/src/RenderHUDLayerTask.cpp +++ b/libraries/render-utils/src/RenderHUDLayerTask.cpp @@ -47,14 +47,15 @@ void RenderHUDLayerTask::build(JobModel& task, const render::Varying& input, ren const auto& lightingModel = inputs[1]; const auto& hudOpaque = inputs[2]; const auto& hudTransparent = inputs[3]; + const auto& hazeFrame = inputs[4]; // Composite the HUD and HUD overlays task.addJob("HUD", primaryFramebuffer); // And HUD Layer objects const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); - const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying(); - const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying(); + const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, hazeFrame, nullJitter).asVarying(); + const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, hazeFrame, nullJitter).asVarying(); task.addJob("DrawHUDOpaque", hudOpaquesInputs, true); task.addJob("DrawHUDTransparent", hudTransparentsInputs, false); } diff --git a/libraries/render-utils/src/RenderHUDLayerTask.h b/libraries/render-utils/src/RenderHUDLayerTask.h index 78cd009636..c30b0498a8 100644 --- a/libraries/render-utils/src/RenderHUDLayerTask.h +++ b/libraries/render-utils/src/RenderHUDLayerTask.h @@ -10,7 +10,7 @@ #define hifi_RenderHUDLayerTask_h #include "LightingModel.h" - +#include "HazeStage.h" class CompositeHUD { public: @@ -25,7 +25,7 @@ public: class RenderHUDLayerTask { public: // Framebuffer where to draw, lighting model, opaque items, transparent items - using Input = render::VaryingSet4; + using Input = render::VaryingSet5; using JobModel = render::Task::ModelI; void build(JobModel& task, const render::Varying& input, render::Varying& output); diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index 4ef7621b36..8e2b38b478 100644 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -15,7 +15,7 @@ <@include render-utils/ShaderConstants.h@> <@include GlobalLight.slh@> -<$declareEvalSkyboxGlobalColor(isScattering)$> +<$declareEvalSkyboxGlobalColor(isScattering, _SCRIBE_NULL)$> layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy diff --git a/libraries/render-utils/src/directional_skybox_light_shadow.slf b/libraries/render-utils/src/directional_skybox_light_shadow.slf index 217cf3ba05..2f289ed00f 100644 --- a/libraries/render-utils/src/directional_skybox_light_shadow.slf +++ b/libraries/render-utils/src/directional_skybox_light_shadow.slf @@ -15,7 +15,7 @@ <@include render-utils/ShaderConstants.h@> <@include GlobalLight.slh@> -<$declareEvalSkyboxGlobalColor(isScattering)$> +<$declareEvalSkyboxGlobalColor(isScattering, _SCRIBE_NULL)$> <@include Shadow.slh@> diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index b3167dd598..3e4711dac8 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -26,7 +26,7 @@ <@endif@> <$declareEvalGlobalLightingAlphaBlended()$> <@else@> - <$declareEvalSkyboxGlobalColor()$> + <$declareEvalSkyboxGlobalColor(_SCRIBE_NULL, HIFI_USE_FORWARD)$> <@endif@> <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> @@ -195,6 +195,7 @@ void main(void) { <@else@> vec3 fragNormalWS = _normalWS; <@endif@> + fragNormalWS = normalize(fragNormalWS); <@if HIFI_USE_FORWARD@> TransformCamera cam = getTransformCamera(); @@ -253,7 +254,7 @@ void main(void) { <@if not HIFI_USE_TRANSLUCENT@> <@if not HIFI_USE_LIGHTMAP@> packDeferredFragment( - normalize(fragNormalWS), + fragNormalWS, opacity, albedo, roughness, @@ -267,7 +268,7 @@ void main(void) { scattering); <@else@> packDeferredFragmentLightmap( - normalize(fragNormalWS), + fragNormalWS, evalOpaqueFinalAlpha(getMaterialOpacity(mat), opacity), albedo, roughness, @@ -301,7 +302,7 @@ void main(void) { 1.0, occlusion, _positionES.xyz, - fragPositionWS, + fragNormalWS, albedo, fresnel, metallic, diff --git a/libraries/render-utils/src/render-utils/ShaderConstants.h b/libraries/render-utils/src/render-utils/ShaderConstants.h index 76c8dd4981..19eb4dd249 100644 --- a/libraries/render-utils/src/render-utils/ShaderConstants.h +++ b/libraries/render-utils/src/render-utils/ShaderConstants.h @@ -68,7 +68,6 @@ #define RENDER_UTILS_BUFFER_LIGHT_CLUSTER_CONTENT 12 // Haze -#define RENDER_UTILS_BUFFER_HAZE_PARAMS 7 #define RENDER_UTILS_TEXTURE_HAZE_COLOR 0 #define RENDER_UTILS_TEXTURE_HAZE_LINEAR_DEPTH 1 @@ -143,7 +142,6 @@ enum Buffer { DeferredFrameTransform = RENDER_UTILS_BUFFER_DEFERRED_FRAME_TRANSFORM, LightModel = RENDER_UTILS_BUFFER_LIGHT_MODEL, AmbientLight = RENDER_UTILS_BUFFER_AMBIENT_LIGHT, - HazeParams = RENDER_UTILS_BUFFER_HAZE_PARAMS, FadeParameters = RENDER_UTILS_BUFFER_FADE_PARAMS, FadeObjectParameters = RENDER_UTILS_BUFFER_FADE_OBJECT_PARAMS, LightClusterFrustumGrid = RENDER_UTILS_BUFFER_LIGHT_CLUSTER_FRUSTUM_GRID, diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index a5a7cfb6a4..ac064e5c8f 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -13,10 +13,10 @@ <@include DefaultMaterials.slh@> <@include GlobalLight.slh@> - <@if HIFI_USE_FORWARD@> - <$declareEvalSkyboxGlobalColor()$> - <@else@> + <@if HIFI_USE_TRANSLUCENT@> <$declareEvalGlobalLightingAlphaBlended()$> + <@else@> + <$declareEvalSkyboxGlobalColor(_SCRIBE_NULL, HIFI_USE_FORWARD)$> <@endif@> <@include gpu/Transform.slh@> @@ -65,19 +65,7 @@ void main() { TransformCamera cam = getTransformCamera(); vec3 fragPosition = _positionES.xyz; - <@if HIFI_USE_FORWARD@> - _fragColor0 = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS), - _color.rgb, - DEFAULT_FRESNEL, - DEFAULT_METALLIC, - DEFAULT_ROUGHNESS), - alpha); - <@else@> + <@if HIFI_USE_TRANSLUCENT@> _fragColor0 = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, 1.0, @@ -90,6 +78,18 @@ void main() { DEFAULT_EMISSIVE, DEFAULT_ROUGHNESS, alpha), alpha); + <@else@> + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normalWS), + _color.rgb, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_ROUGHNESS), + alpha); <@endif@> <@else@> packDeferredFragment( diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index ac7deedff0..9760216682 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -26,12 +26,12 @@ <@endif@> <@if not HIFI_USE_UNLIT@> - <@if HIFI_USE_FORWARD@> - <@include GlobalLight.slh@> - <$declareEvalSkyboxGlobalColor()$> - <@elif HIFI_USE_TRANSLUCENT@> + <@if HIFI_USE_TRANSLUCENT@> <@include GlobalLight.slh@> <$declareEvalGlobalLightingAlphaBlended()$> + <@elif HIFI_USE_FORWARD@> + <@include GlobalLight.slh@> + <$declareEvalSkyboxGlobalColor(_SCRIBE_NULL, HIFI_USE_FORWARD)$> <@else@> <@include DeferredBufferWrite.slh@> <@endif@> @@ -88,19 +88,7 @@ void main(void) { <@endif@> <@if not HIFI_USE_UNLIT@> - <@if HIFI_USE_FORWARD@> - _fragColor0 = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), - texel.rgb, - fresnel, - metallic, - DEFAULT_ROUGHNESS), - texel.a); - <@elif HIFI_USE_TRANSLUCENT@> + <@if HIFI_USE_TRANSLUCENT@> _fragColor0 = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, 1.0, @@ -117,6 +105,18 @@ void main(void) { , DEFAULT_ROUGHNESS, texel.a), texel.a); + <@elif HIFI_USE_FORWARD@> + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + texel.rgb, + fresnel, + metallic, + DEFAULT_ROUGHNESS), + texel.a); <@else@> packDeferredFragment( normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), diff --git a/libraries/render-utils/src/web_browser.slf b/libraries/render-utils/src/web_browser.slf index 7898df1c4c..73745edf9e 100644 --- a/libraries/render-utils/src/web_browser.slf +++ b/libraries/render-utils/src/web_browser.slf @@ -21,7 +21,9 @@ LAYOUT(binding=0) uniform sampler2D webTexture; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; +<@if not HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; +<@endif@> layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy diff --git a/libraries/render-utils/src/web_browser.slv b/libraries/render-utils/src/web_browser.slv index 019486fbf3..d8da7d730b 100644 --- a/libraries/render-utils/src/web_browser.slv +++ b/libraries/render-utils/src/web_browser.slv @@ -17,7 +17,9 @@ <@include render-utils/ShaderConstants.h@> -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; +<@if not HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; +<@endif@> layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; @@ -28,5 +30,8 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + +<@if not HIFI_USE_FORWARD@> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> +<@endif@> } \ No newline at end of file diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 21af30c584..12947f5291 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -104,7 +104,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->fadeMaskTextureUnit = reflection.validTexture(render_utils::slot::texture::FadeMask); locations->fadeParameterBufferUnit = reflection.validUniformBuffer(render_utils::slot::buffer::FadeParameters); locations->fadeObjectParameterBufferUnit = reflection.validUniformBuffer(render_utils::slot::buffer::FadeObjectParameters); - locations->hazeParameterBufferUnit = reflection.validUniformBuffer(render_utils::slot::buffer::HazeParams); + locations->hazeParameterBufferUnit = reflection.validUniformBuffer(graphics::slot::buffer::HazeParams); if (key.isTranslucent()) { locations->lightClusterGridBufferUnit = reflection.validUniformBuffer(render_utils::slot::buffer::LightClusterGrid); locations->lightClusterContentBufferUnit = reflection.validUniformBuffer(render_utils::slot::buffer::LightClusterContent); @@ -134,7 +134,7 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke auto factoryIt = ShapePipeline::_globalCustomFactoryMap.find(key.getCustom()); if ((factoryIt != ShapePipeline::_globalCustomFactoryMap.end()) && (factoryIt)->second) { // found a factory for the custom key, can now generate a shape pipeline for this case: - addPipelineHelper(Filter(key), key, 0, (factoryIt)->second(*this, key, *(args->_batch))); + addPipelineHelper(Filter(key), key, 0, (factoryIt)->second(*this, key, args)); return pickPipeline(args, key); } else { diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index ad91ea61ef..cf41c85dd9 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -272,7 +272,7 @@ protected: ItemSetter _itemSetter; public: using CustomKey = uint8_t; - using CustomFactory = std::function (const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch)>; + using CustomFactory = std::function (const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args)>; using CustomFactoryMap = std::map; static CustomFactoryMap _globalCustomFactoryMap; From 2ffacfea83ecedc643b5aaa59e94cc7fb300e912 Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Thu, 11 Jul 2019 08:51:47 -0700 Subject: [PATCH 25/77] change script params --- launchers/darwin/src/Launcher.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index 71eb7828e9..1a84e9143d 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -442,7 +442,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; NSString* contentPath = [[self getDownloadPathForContentAndScripts] stringByAppendingString:@"content"]; NSString* displayName = [ self displayName]; - NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUI/"]; + NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUIBootstrapper.js"]; NSString* domainUrl = [[Settings sharedSettings] getDomainUrl]; NSString* userToken = [[Launcher sharedLauncher] getTokenString]; NSString* homeBookmark = [[NSString stringWithFormat:@"hqhome="] stringByAppendingString:domainUrl]; @@ -453,7 +453,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; @"--tokens", userToken, @"--cache", contentPath, @"--displayName", displayName, - @"--scripts", scriptsPath, + @"--defaultScriptsOverride", scriptsPath, @"--setBookmark", homeBookmark, @"--no-updater", @"--no-launcher", nil]; @@ -461,7 +461,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; arguments = [NSArray arrayWithObjects: @"--url" , domainUrl, @"--cache", contentPath, - @"--scripts", scriptsPath, + @"--defaultScriptsOverride", scriptsPath, @"--setBookmark", homeBookmark, @"--no-updater", @"--no-launcher", nil]; From 9c56f7466246f619e1f410b608721d85ac23ab40 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 11 Jul 2019 10:28:49 -0700 Subject: [PATCH 26/77] Get recent builds asynchronously --- launchers/win32/LauncherDlg.cpp | 2 +- launchers/win32/LauncherManager.cpp | 121 ++++++++++++++-------------- launchers/win32/LauncherManager.h | 7 +- launchers/win32/LauncherUtils.cpp | 39 +++++++-- launchers/win32/LauncherUtils.h | 49 +++++++---- 5 files changed, 135 insertions(+), 83 deletions(-) diff --git a/launchers/win32/LauncherDlg.cpp b/launchers/win32/LauncherDlg.cpp index 704a2f3050..2e5d568839 100644 --- a/launchers/win32/LauncherDlg.cpp +++ b/launchers/win32/LauncherDlg.cpp @@ -672,7 +672,7 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) { theApp._manager.addToLog(_T("Start splash screen")); setDrawDialog(DrawStep::DrawLogo); } - } else if (_splashStep > 100) { + } else if (_splashStep > 100 && !theApp._manager.needsToWait()) { _showSplash = false; if (theApp._manager.shouldShutDown()) { if (_applicationWND != NULL) { diff --git a/launchers/win32/LauncherManager.cpp b/launchers/win32/LauncherManager.cpp index e56e0e71fc..81b76d13e7 100644 --- a/launchers/win32/LauncherManager.cpp +++ b/launchers/win32/LauncherManager.cpp @@ -25,34 +25,7 @@ void LauncherManager::init() { initLog(); addToLog(_T("Getting most recent build")); CString response; - LauncherUtils::ResponseError error = getMostRecentBuild(_latestApplicationURL, _latestVersion, response); - if (error == LauncherUtils::ResponseError::NoError) { - addToLog(_T("Latest version: ") + _latestVersion); - CString currentVersion; - if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) { - addToLog(_T("Installed version: ") + currentVersion); - if (_latestVersion.Compare(currentVersion) == 0) { - addToLog(_T("Already running most recent build. Launching interface.exe")); - _shouldLaunch = TRUE; - _shouldShutdown = TRUE; - } else { - addToLog(_T("New build found. Updating")); - _shouldUpdate = TRUE; - } - } else if (_loggedIn) { - addToLog(_T("Interface not found but logged in. Reinstalling")); - _shouldUpdate = TRUE; - } else { - _shouldInstall = TRUE; - } - } else { - _hasFailed = true; - CString msg; - msg.Format(_T("Getting most recent build has failed with error: %d"), error); - addToLog(msg); - msg.Format(_T("Response: %s"), response); - addToLog(msg); - } + getMostRecentBuild(_latestApplicationURL, _latestVersion, response); } BOOL LauncherManager::initLog() { @@ -387,39 +360,71 @@ LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString return LauncherUtils::ResponseError::ParsingJSON; } -LauncherUtils::ResponseError LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut, - CString& response) { +void LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut, CString& response) { CString contentTypeJson = L"content-type:application/json"; - LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher", - L"thunder.highfidelity.com", - L"/builds/api/tags/latest?format=json", - contentTypeJson, CStringA(), - response, false); - if (error != LauncherUtils::ResponseError::NoError) { - return error; - } - Json::Value json; - if (LauncherUtils::parseJSON(response, json)) { - int count = json["count"].isInt() ? json["count"].asInt() : 0; - if (count > 0 && json["results"].isArray()) { - for (int i = 0; i < count; i++) { - if (json["results"][i].isObject()) { - Json::Value result = json["results"][i]; - if (result["latest_version"].isInt()) { - std::string version = std::to_string(result["latest_version"].asInt()); - versionOut = CString(version.c_str()); - } - if (result["installers"].isObject() && - result["installers"]["windows"].isObject() && - result["installers"]["windows"]["zip_url"].isString()) { - urlOut = result["installers"]["windows"]["zip_url"].asCString(); - return LauncherUtils::ResponseError::NoError; + std::function httpCallback = [&](CString response, int err) { + LauncherUtils::ResponseError error = LauncherUtils::ResponseError(err); + if (error == LauncherUtils::ResponseError::NoError) { + Json::Value json; + error = LauncherUtils::ResponseError::ParsingJSON; + if (LauncherUtils::parseJSON(response, json)) { + int count = json["count"].isInt() ? json["count"].asInt() : 0; + if (count > 0 && json["results"].isArray()) { + for (int i = 0; i < count; i++) { + if (json["results"][i].isObject()) { + Json::Value result = json["results"][i]; + if (result["latest_version"].isInt()) { + std::string version = std::to_string(result["latest_version"].asInt()); + versionOut = CString(version.c_str()); + } + if (result["installers"].isObject() && + result["installers"]["windows"].isObject() && + result["installers"]["windows"]["zip_url"].isString()) { + urlOut = result["installers"]["windows"]["zip_url"].asCString(); + error = LauncherUtils::ResponseError::NoError; + } + } } } } + onMostRecentBuildReceived(response, error); } + }; + LauncherUtils::httpCallOnThread(L"HQ Launcher", + L"thunder.highfidelity.com", + L"/builds/api/tags/latest?format=json", + contentTypeJson, CStringA(), false, httpCallback); +} + +void LauncherManager::onMostRecentBuildReceived(const CString& response, LauncherUtils::ResponseError error) { + if (error == LauncherUtils::ResponseError::NoError) { + addToLog(_T("Latest version: ") + _latestVersion); + CString currentVersion; + if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) { + addToLog(_T("Installed version: ") + currentVersion); + if (_latestVersion.Compare(currentVersion) == 0) { + addToLog(_T("Already running most recent build. Launching interface.exe")); + _shouldLaunch = TRUE; + _shouldShutdown = TRUE; + } else { + addToLog(_T("New build found. Updating")); + _shouldUpdate = TRUE; + } + } else if (_loggedIn) { + addToLog(_T("Interface not found but logged in. Reinstalling")); + _shouldUpdate = TRUE; + } else { + _shouldInstall = TRUE; + } + _shouldWait = FALSE; + } else { + _hasFailed = true; + CString msg; + msg.Format(_T("Getting most recent build has failed with error: %d"), error); + addToLog(msg); + msg.Format(_T("Response: %s"), response); + addToLog(msg); } - return LauncherUtils::ResponseError::ParsingJSON; } LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const CString& username, @@ -603,12 +608,10 @@ BOOL LauncherManager::downloadFile(ProcessType type, const CString& url, CString std::function onDownloadFinished = [&](int type, bool error) { if (!error) { onFileDownloaded((ProcessType)type); - } - else { + } else { if (type == ProcessType::DownloadApplication) { addToLog(_T("Error downloading content.")); - } - else { + } else { addToLog(_T("Error downloading application.")); } _hasFailed = true; diff --git a/launchers/win32/LauncherManager.h b/launchers/win32/LauncherManager.h index cb707e0a14..e97ae6efcc 100644 --- a/launchers/win32/LauncherManager.h +++ b/launchers/win32/LauncherManager.h @@ -67,7 +67,7 @@ public: BOOL isApplicationInstalled(CString& version, CString& domain, CString& content, bool& loggedIn); LauncherUtils::ResponseError getAccessTokenForCredentials(const CString& username, const CString& password); - LauncherUtils::ResponseError getMostRecentBuild(CString& urlOut, CString& versionOut, CString& response); + void getMostRecentBuild(CString& urlOut, CString& versionOut, CString& response); LauncherUtils::ResponseError readOrganizationJSON(const CString& hash); LauncherUtils::ResponseError readConfigJSON(CString& version, CString& domain, CString& content, bool& loggedIn); @@ -90,12 +90,13 @@ public: BOOL needsUpdate() { return _shouldUpdate; } BOOL needsUninstall() { return _shouldUninstall; } BOOL needsInstall() { return _shouldInstall; } + BOOL needsToWait() { return _shouldWait; } void setDisplayName(const CString& displayName) { _displayName = displayName; } bool isLoggedIn() { return _loggedIn; } bool hasFailed() { return _hasFailed; } void setFailed(bool hasFailed) { _hasFailed = hasFailed; } const CString& getLatestInterfaceURL() const { return _latestApplicationURL; } - void uninstall() { _shouldUninstall = true; }; + void uninstall() { _shouldUninstall = true; _shouldWait = false; }; BOOL downloadFile(ProcessType type, const CString& url, CString& localPath); BOOL downloadContent(); @@ -110,6 +111,7 @@ public: private: ProcessType _currentProcess { ProcessType::DownloadApplication }; + void onMostRecentBuildReceived(const CString& response, LauncherUtils::ResponseError error); CString _latestApplicationURL; CString _latestVersion; CString _contentURL; @@ -126,6 +128,7 @@ private: BOOL _shouldInstall { FALSE }; BOOL _shouldShutdown { FALSE }; BOOL _shouldLaunch { FALSE }; + BOOL _shouldWait { TRUE }; float _progress { 0.0f }; CStdioFile _logFile; }; diff --git a/launchers/win32/LauncherUtils.cpp b/launchers/win32/LauncherUtils.cpp index 3ba4b26901..e0a85302f0 100644 --- a/launchers/win32/LauncherUtils.cpp +++ b/launchers/win32/LauncherUtils.cpp @@ -470,9 +470,9 @@ BOOL LauncherUtils::hMac256(const CString& cmessage, const char* keystr, CString DWORD WINAPI LauncherUtils::unzipThread(LPVOID lpParameter) { UnzipThreadData& data = *((UnzipThreadData*)lpParameter); - uint64_t size = LauncherUtils::extractZip(data._zipFile, data._path, std::vector(), data.progressCallback); + uint64_t size = LauncherUtils::extractZip(data._zipFile, data._path, std::vector(), data._progressCallback); int mb_size = (int)(size * 0.001f); - data.callback(data._type, mb_size); + data._callback(data._type, mb_size); delete &data; return 0; } @@ -480,17 +480,26 @@ DWORD WINAPI LauncherUtils::unzipThread(LPVOID lpParameter) { DWORD WINAPI LauncherUtils::downloadThread(LPVOID lpParameter) { DownloadThreadData& data = *((DownloadThreadData*)lpParameter); ProgressCallback progressCallback; - progressCallback.setProgressCallback(data.progressCallback); + progressCallback.setProgressCallback(data._progressCallback); auto hr = URLDownloadToFile(0, data._url, data._file, 0, static_cast(&progressCallback)); - data.callback(data._type, hr != S_OK); + data._callback(data._type, hr != S_OK); return 0; } DWORD WINAPI LauncherUtils::deleteDirectoryThread(LPVOID lpParameter) { DeleteThreadData& data = *((DeleteThreadData*)lpParameter); BOOL success = LauncherUtils::deleteFileOrDirectory(data._dirPath); - data.callback(!success); + data._callback(!success); + return 0; +} + +DWORD WINAPI LauncherUtils::httpThread(LPVOID lpParameter) { + HttpThreadData& data = *((HttpThreadData*)lpParameter); + CString response; + auto error = LauncherUtils::makeHTTPCall(data._callerName, data._mainUrl, data._dirUrl, + data._contentType, data._postData, response, data._isPost); + data._callback(response, error); return 0; } @@ -543,6 +552,26 @@ BOOL LauncherUtils::deleteDirectoryOnThread(const CString& dirPath, std::functio return FALSE; } +BOOL LauncherUtils::httpCallOnThread(const CString& callerName, const CString& mainUrl, const CString& dirUrl, + const CString& contentType, CStringA& postData, bool isPost, + std::function callback) { + DWORD myThreadID; + HttpThreadData* httpThreadData = new HttpThreadData(); + httpThreadData->_callerName = callerName; + httpThreadData->_mainUrl = mainUrl; + httpThreadData->_dirUrl = dirUrl; + httpThreadData->_contentType = contentType; + httpThreadData->_postData = postData; + httpThreadData->_isPost = isPost; + httpThreadData->setCallback(callback); + HANDLE myHandle = CreateThread(0, 0, httpThread, httpThreadData, 0, &myThreadID); + if (myHandle) { + CloseHandle(myHandle); + return TRUE; + } + return FALSE; +} + HWND LauncherUtils::executeOnForeground(const CString& path, const CString& params) { SHELLEXECUTEINFO info; info.cbSize = sizeof(SHELLEXECUTEINFO); diff --git a/launchers/win32/LauncherUtils.h b/launchers/win32/LauncherUtils.h index 3e07d2af05..32cd5031b4 100644 --- a/launchers/win32/LauncherUtils.h +++ b/launchers/win32/LauncherUtils.h @@ -55,15 +55,15 @@ public: ULONG ulStatusCode, LPCWSTR szStatusText) { float progress = (float)ulProgress / ulProgressMax; if (!isnan(progress)) { - onProgressCallback(progress); + _onProgressCallback(progress); } return S_OK; } void setProgressCallback(std::function fn) { - onProgressCallback = std::bind(fn, std::placeholders::_1); + _onProgressCallback = std::bind(fn, std::placeholders::_1); } private: - std::function onProgressCallback; + std::function _onProgressCallback; }; enum ResponseError { @@ -82,14 +82,14 @@ public: int _type; CString _url; CString _file; - std::function callback; - std::function progressCallback; + std::function _callback; + std::function _progressCallback; // function(type, errorType) void setCallback(std::function fn) { - callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2); + _callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2); } void setProgressCallback(std::function fn) { - progressCallback = std::bind(fn, std::placeholders::_1); + _progressCallback = std::bind(fn, std::placeholders::_1); } }; @@ -98,23 +98,36 @@ public: std::string _zipFile; std::string _path; // function(type, size) - std::function callback; - std::function progressCallback; + std::function _callback; + std::function _progressCallback; void setCallback(std::function fn) { - callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2); + _callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2); } void setProgressCallback(std::function fn) { - progressCallback = std::bind(fn, std::placeholders::_1); + _progressCallback = std::bind(fn, std::placeholders::_1); } }; struct DeleteThreadData { CString _dirPath; - std::function callback; - std::function progressCallback; - void setCallback(std::function fn) { callback = std::bind(fn, std::placeholders::_1); } + std::function _callback; + std::function _progressCallback; + void setCallback(std::function fn) { _callback = std::bind(fn, std::placeholders::_1); } void setProgressCallback(std::function fn) { - progressCallback = std::bind(fn, std::placeholders::_1); + _progressCallback = std::bind(fn, std::placeholders::_1); + } + }; + + struct HttpThreadData { + CString _callerName; + CString _mainUrl; + CString _dirUrl; + CString _contentType; + CStringA _postData; + bool _isPost { false }; + std::function _callback; + void setCallback(std::function fn) { + _callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2); } }; @@ -150,6 +163,9 @@ public: std::function callback, std::function progressCallback); static BOOL deleteDirectoryOnThread(const CString& dirPath, std::function callback); + static BOOL httpCallOnThread(const CString& callerName, const CString& mainUrl, const CString& dirUrl, + const CString& contentType, CStringA& postData, bool isPost, + std::function callback); static CString urlEncodeString(const CString& url); static HWND executeOnForeground(const CString& path, const CString& params); @@ -159,4 +175,5 @@ private: static DWORD WINAPI unzipThread(LPVOID lpParameter); static DWORD WINAPI downloadThread(LPVOID lpParameter); static DWORD WINAPI deleteDirectoryThread(LPVOID lpParameter); -}; \ No newline at end of file + static DWORD WINAPI httpThread(LPVOID lpParameter); +}; From 8d3dc52ac04fbde50649d8a46d9d370fe4701674 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 11 Jul 2019 10:58:31 -0700 Subject: [PATCH 27/77] mac sleep monitor checkpoint --- interface/src/Application.cpp | 16 ++++++++++ interface/src/MacHelper.cpp | 57 +++++++++++++++++++++++++++++++++++ interface/src/MacHelper.h | 21 +++++++++++++ 3 files changed, 94 insertions(+) create mode 100755 interface/src/MacHelper.cpp create mode 100755 interface/src/MacHelper.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b59fd223ba..a098f965d8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -257,6 +257,10 @@ extern "C" { } #endif +#ifdef Q_OS_MAC +#include "MacHelper.h" +#endif + #if defined(Q_OS_ANDROID) #include #include "AndroidHelper.h" @@ -960,6 +964,9 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); +#ifdef Q_OS_MAC + DependencyManager::set(); +#endif QString setBookmarkValue = getCmdOption(argc, constArgv, "--setBookmark"); if (!setBookmarkValue.isEmpty()) { @@ -2829,17 +2836,20 @@ void Application::cleanupBeforeQuit() { } Application::~Application() { + qCInfo(interfaceapp) << "HRS FIXME Quit 1"; // remove avatars from physics engine auto avatarManager = DependencyManager::get(); avatarManager->clearOtherAvatars(); auto myCharacterController = getMyAvatar()->getCharacterController(); myCharacterController->clearDetailedMotionStates(); + qCInfo(interfaceapp) << "HRS FIXME Quit 2"; PhysicsEngine::Transaction transaction; avatarManager->buildPhysicsTransaction(transaction); _physicsEngine->processTransaction(transaction); avatarManager->handleProcessedPhysicsTransaction(transaction); avatarManager->deleteAllAvatars(); + qCInfo(interfaceapp) << "HRS FIXME Quit 3"; _physicsEngine->setCharacterController(nullptr); @@ -2850,9 +2860,15 @@ Application::~Application() { // shutdown graphics engine _graphicsEngine.shutdown(); + qCInfo(interfaceapp) << "HRS FIXME Quit 4"; _gameWorkload.shutdown(); + qCInfo(interfaceapp) << "HRS FIXME Quit 5"; DependencyManager::destroy(); + qCInfo(interfaceapp) << "HRS FIXME Quit 6"; +#ifdef Q_OS_MAC + DependencyManager::destroy(); +#endif _entityClipboard->eraseAllOctreeElements(); _entityClipboard.reset(); diff --git a/interface/src/MacHelper.cpp b/interface/src/MacHelper.cpp new file mode 100755 index 0000000000..f6b76649cd --- /dev/null +++ b/interface/src/MacHelper.cpp @@ -0,0 +1,57 @@ +// +// MacHelper.h +// interface/src +// +// Created by Howard Stearns +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "InterfaceLogging.h" +#include "MacHelper.h" + +#ifdef Q_OS_MAC +#include +#include + +io_connect_t root_port; +IONotificationPortRef notifyPortRef; +io_object_t notifierObject; +void* refCon; + +void sleepHandler(void* refCon, io_service_t service, natural_t messageType, void* messageArgument) { + qCInfo(interfaceapp) << "HRS FIXME sleepHandler."; + if (messageType == kIOMessageSystemHasPoweredOn) { + qCInfo(interfaceapp) << "HRS FIXME Waking up from sleep or hybernation."; + } +} +#endif + +MacHelper::MacHelper() { + qCInfo(interfaceapp) << "HRS FIXME Start MacHelper."; +#ifdef Q_OS_MAC + root_port = IORegisterForSystemPower(refCon, ¬ifyPortRef, sleepHandler, ¬ifierObject); + if (root_port == 0) { + qCWarning(interfaceapp) << "IORegisterForSystemPower failed"; + } else { + qCDebug(interfaceapp) << "HRS FIXME IORegisterForSystemPower OK"; + } + CFRunLoopAddSource(CFRunLoopGetCurrent(), + IONotificationPortGetRunLoopSource(notifyPortRef), + kCFRunLoopCommonModes); +#endif +} + +MacHelper::~MacHelper() { + qCInfo(interfaceapp) << "HRS FIXME End MacHelper."; +#ifdef Q_OS_MAC + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), + IONotificationPortGetRunLoopSource(notifyPortRef), + kCFRunLoopCommonModes); + IODeregisterForSystemPower(¬ifierObject); + IOServiceClose(root_port); + IONotificationPortDestroy(notifyPortRef); +#endif +} diff --git a/interface/src/MacHelper.h b/interface/src/MacHelper.h new file mode 100755 index 0000000000..52ad4d3e55 --- /dev/null +++ b/interface/src/MacHelper.h @@ -0,0 +1,21 @@ +// +// MacHelper.h +// interface/src +// +// Created by Howard Stearns +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once + +#include "DependencyManager.h" + +class MacHelper : public Dependency { +public: + MacHelper(); + ~MacHelper(); +}; + From 953966474944028f8818321d44f7c14a6144da0b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 11 Jul 2019 10:58:48 -0700 Subject: [PATCH 28/77] add haze to skybox --- cmake/macros/AutoScribeShader.cmake | 2 ++ libraries/graphics/src/graphics/skybox.slf | 25 ++++++++++++++++++++-- libraries/render-utils/src/Haze.slf | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake index 63f7c0c7d6..f0f1fe1d05 100755 --- a/cmake/macros/AutoScribeShader.cmake +++ b/cmake/macros/AutoScribeShader.cmake @@ -319,6 +319,7 @@ macro(AUTOSCRIBE_SHADER_LIB) unset(SHADER_FILE) unset(SHADER_FILE CACHE) find_file(SHADER_FILE "${VERTEX_NAME}.slv" PATHS "${PROGRAM_FOLDER}" PATH_SUFFIXES "..") + message("boop ${SHADER_FILE} ${VERTEX_NAME} ${PROGRAM_FOLDER}") AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) string(CONCAT VERTEX_ENUMS "${VERTEX_ENUMS}" "${SHADER_LIST}") else() @@ -337,6 +338,7 @@ macro(AUTOSCRIBE_SHADER_LIB) unset(SHADER_FILE) unset(SHADER_FILE CACHE) find_file(SHADER_FILE "${FRAGMENT_NAME}.slf" PATHS "${PROGRAM_FOLDER}" PATH_SUFFIXES "..") + message("boop2 ${SHADER_FILE} ${FRAGMENT_NAME} ${PROGRAM_FOLDER}") AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) string(CONCAT FRAGMENT_ENUMS "${FRAGMENT_ENUMS}" "${SHADER_LIST}") else() diff --git a/libraries/graphics/src/graphics/skybox.slf b/libraries/graphics/src/graphics/skybox.slf index 0dea1d7882..4ae53a657f 100755 --- a/libraries/graphics/src/graphics/skybox.slf +++ b/libraries/graphics/src/graphics/skybox.slf @@ -12,6 +12,12 @@ <@include graphics/ShaderConstants.h@> <@if HIFI_USE_FORWARD@> + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + + <@include graphics/Light.slh@> + <$declareLightBuffer()$> + <@include graphics/Haze.slh@> <@endif@> @@ -35,13 +41,28 @@ void main(void) { // mix(skyboxColor, skyboxTexel, skybox.color.a) // and the blend factor should be user controlled - vec3 skyboxTexel = texture(cubeMap, normalize(_normal)).rgb; + vec3 normal = normalize(_normal); + vec3 skyboxTexel = texture(cubeMap, normal).rgb; vec3 skyboxColor = skybox.color.rgb; _fragColor = vec4(mix(vec3(1.0), skyboxTexel, float(skybox.color.a > 0.0)) * mix(vec3(1.0), skyboxColor, float(skybox.color.a < 1.0)), 1.0); <@if HIFI_USE_FORWARD@> - _fragColor = vec4(hazeParams.hazeColor, 1); + // FIXME: either move this elsewhere or give it access to isHazeEnabled() (which is in render-utils/LightingModel.slh) + if (/*(isHazeEnabled() > 0.0) && */(hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + TransformCamera cam = getTransformCamera(); + vec4 eyePositionWS = cam._viewInverse[3]; + // We choose an arbitrary large number > BLEND_DISTANCE in Haze.slh + const float SKYBOX_DISTANCE = 32000.0; + vec4 fragPositionWS = eyePositionWS + SKYBOX_DISTANCE * vec4(normal, 0.0); + vec4 fragPositionES = cam._view * fragPositionWS; + + Light light = getKeyLight(); + vec3 lightDirectionWS = getLightDirection(light); + + vec4 hazeColor = computeHazeColor(fragPositionES.xyz, fragPositionWS.xyz, eyePositionWS.xyz, lightDirectionWS); + _fragColor.rgb = mix(_fragColor.rgb, hazeColor.rgb, hazeColor.a); + } <@endif@> } diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index 951841ad49..899f36b8eb 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -15,9 +15,9 @@ <$declareDeferredFrameTransform()$> <@include graphics/Light.slh@> +<$declareLightBuffer()$> <@include LightingModel.slh@> -<$declareLightBuffer()$> <@include graphics/Haze.slh@> From bc5f8ad77543f7ea31e447f2ea22986db5814ac1 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 11 Jul 2019 11:13:58 -0700 Subject: [PATCH 29/77] Remove unneeded response --- launchers/win32/LauncherManager.cpp | 5 ++--- launchers/win32/LauncherManager.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/launchers/win32/LauncherManager.cpp b/launchers/win32/LauncherManager.cpp index 81b76d13e7..294c9742f5 100644 --- a/launchers/win32/LauncherManager.cpp +++ b/launchers/win32/LauncherManager.cpp @@ -24,8 +24,7 @@ LauncherManager::~LauncherManager() { void LauncherManager::init() { initLog(); addToLog(_T("Getting most recent build")); - CString response; - getMostRecentBuild(_latestApplicationURL, _latestVersion, response); + getMostRecentBuild(_latestApplicationURL, _latestVersion); } BOOL LauncherManager::initLog() { @@ -360,7 +359,7 @@ LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString return LauncherUtils::ResponseError::ParsingJSON; } -void LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut, CString& response) { +void LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut) { CString contentTypeJson = L"content-type:application/json"; std::function httpCallback = [&](CString response, int err) { LauncherUtils::ResponseError error = LauncherUtils::ResponseError(err); diff --git a/launchers/win32/LauncherManager.h b/launchers/win32/LauncherManager.h index e97ae6efcc..6ebebc5fc3 100644 --- a/launchers/win32/LauncherManager.h +++ b/launchers/win32/LauncherManager.h @@ -67,7 +67,7 @@ public: BOOL isApplicationInstalled(CString& version, CString& domain, CString& content, bool& loggedIn); LauncherUtils::ResponseError getAccessTokenForCredentials(const CString& username, const CString& password); - void getMostRecentBuild(CString& urlOut, CString& versionOut, CString& response); + void getMostRecentBuild(CString& urlOut, CString& versionOut); LauncherUtils::ResponseError readOrganizationJSON(const CString& hash); LauncherUtils::ResponseError readConfigJSON(CString& version, CString& domain, CString& content, bool& loggedIn); From ba8978862d3acde8c6a22091959b968ab723217e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 11 Jul 2019 11:17:04 -0700 Subject: [PATCH 30/77] improved names for workload::Region constants --- libraries/workload/src/workload/Region.h | 13 ++++++------- libraries/workload/src/workload/RegionTracker.cpp | 2 +- libraries/workload/src/workload/View.cpp | 8 ++++---- libraries/workload/src/workload/View.h | 4 ++-- libraries/workload/src/workload/ViewTask.cpp | 8 ++++---- libraries/workload/src/workload/ViewTask.h | 6 +++--- 6 files changed, 20 insertions(+), 21 deletions(-) diff --git a/libraries/workload/src/workload/Region.h b/libraries/workload/src/workload/Region.h index 6ee3b775ee..b12c5b717c 100644 --- a/libraries/workload/src/workload/Region.h +++ b/libraries/workload/src/workload/Region.h @@ -26,10 +26,9 @@ public: INVALID, // INVALID = not known to workload }; - static const uint8_t NUM_CLASSIFICATIONS = 4; - static const uint8_t NUM_TRANSITIONS = NUM_CLASSIFICATIONS * (NUM_CLASSIFICATIONS - 1); - - static const uint8_t NUM_VIEW_REGIONS = (NUM_CLASSIFICATIONS - 1); + static constexpr uint32_t NUM_KNOWN_REGIONS = uint32_t(Region::R4 - Region::R1 + 1); // R1 through R4 inclusive + static constexpr uint32_t NUM_TRACKED_REGIONS = uint32_t(Region::R3 - Region::R1 + 1); // R1 through R3 inclusive + static const uint8_t NUM_REGION_TRANSITIONS = NUM_KNOWN_REGIONS * (NUM_KNOWN_REGIONS - 1); static uint8_t computeTransitionIndex(uint8_t prevIndex, uint8_t newIndex); @@ -63,11 +62,11 @@ inline uint8_t Region::computeTransitionIndex(uint8_t prevIndex, uint8_t newInde // 3 | | | | | // | 9 | 10 | 11 | -1 | // +-------+-------+-------+-------+ - uint8_t p = prevIndex + Region::NUM_CLASSIFICATIONS * newIndex; - if (0 == (p % (Region::NUM_CLASSIFICATIONS + 1))) { + uint8_t p = prevIndex + Region::NUM_KNOWN_REGIONS * newIndex; + if (0 == (p % (Region::NUM_KNOWN_REGIONS + 1))) { return -1; } - return p - (1 + p / (Region::NUM_CLASSIFICATIONS + 1)); + return p - (1 + p / (Region::NUM_KNOWN_REGIONS + 1)); } } // namespace workload diff --git a/libraries/workload/src/workload/RegionTracker.cpp b/libraries/workload/src/workload/RegionTracker.cpp index 0866c91709..8cd4a67bce 100644 --- a/libraries/workload/src/workload/RegionTracker.cpp +++ b/libraries/workload/src/workload/RegionTracker.cpp @@ -34,7 +34,7 @@ void RegionTracker::run(const WorkloadContextPointer& context, Outputs& outputs) space->categorizeAndGetChanges(outChanges); // use exit/enter lists for each region less than Region::R4 - outRegionChanges.resize(2 * (workload::Region::NUM_CLASSIFICATIONS - 1)); + outRegionChanges.resize(2 * workload::Region::NUM_TRACKED_REGIONS); for (uint32_t i = 0; i < outChanges.size(); ++i) { Space::Change& change = outChanges[i]; if (change.prevRegion < Region::R4) { diff --git a/libraries/workload/src/workload/View.cpp b/libraries/workload/src/workload/View.cpp index a11b1890fd..4d7e610889 100644 --- a/libraries/workload/src/workload/View.cpp +++ b/libraries/workload/src/workload/View.cpp @@ -42,11 +42,11 @@ Sphere View::evalRegionSphere(const View& view, float originRadius, float maxDis } void View::updateRegionsDefault(View& view) { - std::vector config(Region::NUM_VIEW_REGIONS * 2, 0.0f); + std::vector config(Region::NUM_TRACKED_REGIONS * 2, 0.0f); float refFar = 10.0f; float refClose = 2.0f; - for (int i = 0; i < Region::NUM_VIEW_REGIONS; i++) { + for (int i = 0; i < Region::NUM_TRACKED_REGIONS; i++) { float weight = i + 1.0f; config[i * 2] = refClose; config[i * 2 + 1] = refFar * weight; @@ -56,13 +56,13 @@ void View::updateRegionsDefault(View& view) { } void View::updateRegionsFromBackFronts(View& view) { - for (int i = 0; i < Region::NUM_VIEW_REGIONS; i++) { + for (int i = 0; i < Region::NUM_TRACKED_REGIONS; i++) { view.regions[i] = evalRegionSphere(view, view.regionBackFronts[i].x, view.regionBackFronts[i].y); } } void View::updateRegionsFromBackFrontDistances(View& view, const float* configDistances) { - for (int i = 0; i < Region::NUM_VIEW_REGIONS; i++) { + for (int i = 0; i < Region::NUM_TRACKED_REGIONS; i++) { view.regionBackFronts[i] = glm::vec2(configDistances[i * 2], configDistances[i * 2 + 1]); } updateRegionsFromBackFronts(view); diff --git a/libraries/workload/src/workload/View.h b/libraries/workload/src/workload/View.h index 972caf5101..fe7bed0d18 100644 --- a/libraries/workload/src/workload/View.h +++ b/libraries/workload/src/workload/View.h @@ -48,10 +48,10 @@ public: float originRadius{ 0.5f }; // N regions distances - glm::vec2 regionBackFronts[Region::NUM_VIEW_REGIONS + 1]; + glm::vec2 regionBackFronts[Region::NUM_TRACKED_REGIONS]; // N regions spheres - Sphere regions[Region::NUM_VIEW_REGIONS]; + Sphere regions[Region::NUM_TRACKED_REGIONS]; // Set fov properties from angle void setFov(float angleRad); diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 0a268df9fc..715b93618d 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -82,7 +82,7 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i ControlViews::ControlViews() { - for (int32_t i = 0; i < workload::Region::NUM_VIEW_REGIONS; i++) { + for (int32_t i = 0; i < workload::Region::NUM_TRACKED_REGIONS; i++) { regionBackFronts[i] = MIN_VIEW_BACK_FRONTS[i]; regionRegulators[i] = Regulator(std::chrono::milliseconds(2), MIN_VIEW_BACK_FRONTS[i], MAX_VIEW_BACK_FRONTS[i], glm::vec2(RELATIVE_STEP_DOWN), glm::vec2(RELATIVE_STEP_UP)); } @@ -166,7 +166,7 @@ glm::vec2 Regulator::clamp(const glm::vec2& backFront) const { void ControlViews::regulateViews(workload::Views& outViews, const workload::Timings& timings) { for (auto& outView : outViews) { - for (int32_t r = 0; r < workload::Region::NUM_VIEW_REGIONS; r++) { + for (int32_t r = 0; r < workload::Region::NUM_TRACKED_REGIONS; r++) { outView.regionBackFronts[r] = regionBackFronts[r]; } } @@ -198,12 +198,12 @@ void ControlViews::enforceRegionContainment() { // and each region should never exceed its min/max limits const glm::vec2 MIN_REGION_GAP = { 1.0f, 2.0f }; // enforce outside --> in - for (int32_t i = workload::Region::NUM_VIEW_REGIONS - 2; i >= 0; --i) { + for (int32_t i = workload::Region::NUM_TRACKED_REGIONS - 2; i >= 0; --i) { int32_t j = i + 1; regionBackFronts[i] = regionRegulators[i].clamp(glm::min(regionBackFronts[i], regionBackFronts[j] - MIN_REGION_GAP)); } // enforce inside --> out - for (int32_t i = 1; i < workload::Region::NUM_VIEW_REGIONS; ++i) { + for (int32_t i = 1; i < workload::Region::NUM_TRACKED_REGIONS; ++i) { int32_t j = i - 1; regionBackFronts[i] = regionRegulators[i].clamp(glm::max(regionBackFronts[i], regionBackFronts[j] + MIN_REGION_GAP)); } diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index 207bc04276..f6f2faef87 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -196,7 +196,7 @@ namespace workload { } data; struct DataExport { - static const int SIZE{ workload::Region::NUM_VIEW_REGIONS }; + static const int SIZE{ workload::Region::NUM_TRACKED_REGIONS }; float timings[SIZE]; glm::vec2 ranges[SIZE]; QList _timings { 6, 2.0 }; @@ -252,8 +252,8 @@ namespace workload { void configure(const Config& config); void run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs); - std::array regionBackFronts; - std::array regionRegulators; + std::array regionBackFronts; + std::array regionRegulators; void regulateViews(workload::Views& views, const workload::Timings& timings); void enforceRegionContainment(); From ce2b7e5baa07cdb51781125b389ac07892867864 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 11 Jul 2019 12:05:13 -0700 Subject: [PATCH 31/77] Finish all of the logic and most of the layout --- .../resources/qml/controlsUit/ComboBox.qml | 1 + .../dialogs/graphics/GraphicsSettings.qml | 228 +++++++++++++++++- interface/src/PerformanceManager.cpp | 4 +- .../PlatformInfoScriptingInterface.cpp | 4 +- .../PlatformInfoScriptingInterface.h | 7 +- 5 files changed, 235 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/controlsUit/ComboBox.qml b/interface/resources/qml/controlsUit/ComboBox.qml index 8d1d7a5262..1a904df89d 100644 --- a/interface/resources/qml/controlsUit/ComboBox.qml +++ b/interface/resources/qml/controlsUit/ComboBox.qml @@ -22,6 +22,7 @@ FocusScope { property alias editable: comboBox.editable property alias comboBox: comboBox readonly property alias currentText: comboBox.currentText; + property alias displayText: comboBox.displayText; property alias currentIndex: comboBox.currentIndex; property int currentHighLightedIndex: comboBox.currentIndex; diff --git a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml index 530b125ffc..34f1caa737 100644 --- a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml +++ b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml @@ -16,6 +16,7 @@ import QtQuick.Layouts 1.12 import stylesUit 1.0 as HifiStylesUit import controlsUit 1.0 as HifiControlsUit import "qrc:////qml//controls" as HifiControls +import PerformanceEnums 1.0 Flickable { HifiStylesUit.HifiConstants { id: hifi; } @@ -51,6 +52,7 @@ Flickable { ColumnLayout { Layout.topMargin: 10 Layout.preferredWidth: parent.width + Layout.preferredHeight: contentItem.height spacing: 0 HifiControlsUit.RadioButton { @@ -62,6 +64,7 @@ Flickable { checked: Performance.getPerformancePreset() === PerformanceEnums.LOW onClicked: { Performance.setPerformancePreset(PerformanceEnums.LOW); + root.refreshAllDropdowns(); } } @@ -74,6 +77,7 @@ Flickable { checked: Performance.getPerformancePreset() === PerformanceEnums.MID onClicked: { Performance.setPerformancePreset(PerformanceEnums.MID); + root.refreshAllDropdowns(); } } @@ -86,6 +90,7 @@ Flickable { checked: Performance.getPerformancePreset() === PerformanceEnums.HIGH onClicked: { Performance.setPerformancePreset(PerformanceEnums.HIGH); + root.refreshAllDropdowns(); } } @@ -95,9 +100,9 @@ Flickable { fontSize: 16 leftPadding: 0 text: "Custom" - checked: !(performanceLow.checked || performanceMedium.checked || performanceHigh.checked) + checked: Performance.getPerformancePreset() === PerformanceEnums.UNKNOWN onClicked: { - + Performance.setPerformancePreset(PerformanceEnums.UNKNOWN); } } } @@ -105,10 +110,12 @@ Flickable { ColumnLayout { Layout.topMargin: 10 Layout.preferredWidth: parent.width - spacing: 0 + Layout.preferredHeight: contentItem.height + spacing: 30 Item { Layout.preferredWidth: parent.width + Layout.preferredHeight: 35 HifiStylesUit.RalewayRegular { id: resolutionHeader @@ -116,7 +123,7 @@ Flickable { anchors.left: parent.left anchors.top: parent.top width: 130 - height: paintedHeight + height: parent.height size: 16 color: "#FFFFFF" } @@ -128,7 +135,7 @@ Flickable { anchors.leftMargin: 57 anchors.top: parent.top width: 150 - height: resolutionHeader.height + height: parent.height colorScheme: hifi.colorSchemes.dark minimumValue: 0.25 maximumValue: 1.5 @@ -152,7 +159,218 @@ Flickable { } } } + + Item { + Layout.preferredWidth: parent.width + Layout.preferredHeight: 35 + + HifiStylesUit.RalewayRegular { + id: worldDetailHeader + text: "World Detail" + anchors.left: parent.left + anchors.top: parent.top + width: 130 + height: parent.height + size: 16 + color: "#FFFFFF" + } + + ListModel { + id: worldDetailModel + + ListElement { + text: "Low World Detail" + worldDetailQualityValue: 0.25 + } + ListElement { + text: "Medium World Detail" + worldDetailQualityValue: 0.5 + } + ListElement { + text: "Full World Detail" + worldDetailQualityValue: 0.75 + } + } + + HifiControlsUit.ComboBox { + id: worldDetailDropdown + enabled: performanceCustom.checked + anchors.left: worldDetailHeader.right + anchors.leftMargin: 20 + anchors.top: parent.top + width: 280 + height: parent.height + colorScheme: hifi.colorSchemes.dark + model: worldDetailModel + currentIndex: -1 + + function refreshWorldDetailDropdown() { + var currentWorldDetailQuality = LODManager.worldDetailQuality; + if (currentWorldDetailQuality <= 0.25) { + worldDetailDropdown.currentIndex = 0; + } else if (currentWorldDetailQuality <= 0.5) { + worldDetailDropdown.currentIndex = 1; + } else { + worldDetailDropdown.currentIndex = 2; + } + } + + Component.onCompleted: { + worldDetailDropdown.refreshWorldDetailDropdown(); + } + + onCurrentIndexChanged: { + LODManager.worldDetailQuality = model.get(currentIndex).worldDetailQualityValue; + worldDetailDropdown.displayText = model.get(currentIndex).text; + } + } + } + + Item { + Layout.preferredWidth: parent.width + Layout.preferredHeight: 35 + + HifiStylesUit.RalewayRegular { + id: renderingEffectsHeader + text: "Rendering Effects" + anchors.left: parent.left + anchors.top: parent.top + width: 130 + height: parent.height + size: 16 + color: "#FFFFFF" + } + + ListModel { + id: renderingEffectsModel + + ListElement { + text: "No Rendering Effects" + preferredRenderMethod: 1 // "FORWARD" + shadowsEnabled: false + } + ListElement { + text: "Local Lights, Fog, Bloom" + preferredRenderMethod: 0 // "DEFERRED" + shadowsEnabled: false + } + ListElement { + text: "Local Lights, Fog, Bloom, Shadows" + preferredRenderMethod: 0 // "DEFERRED" + shadowsEnabled: true + } + } + + HifiControlsUit.ComboBox { + id: renderingEffectsDropdown + enabled: performanceCustom.checked + anchors.left: renderingEffectsHeader.right + anchors.leftMargin: 20 + anchors.top: parent.top + width: 280 + height: parent.height + colorScheme: hifi.colorSchemes.dark + model: renderingEffectsModel + currentIndex: -1 + + function refreshRenderingEffectsDropdownDisplay() { + if (Render.shadowsEnabled) { + renderingEffectsDropdown.currentIndex = 2; + } else if (Render.renderMethod === 0) { + renderingEffectsDropdown.currentIndex = 1; + } else { + renderingEffectsDropdown.currentIndex = 0; + } + } + + Component.onCompleted: { + renderingEffectsDropdown.refreshRenderingEffectsDropdownDisplay(); + } + + onCurrentIndexChanged: { + var renderMethodToSet = 1; + if (model.get(currentIndex).preferredRenderMethod === 0 && + PlatformInfo.isRenderMethodDeferredCapable()) { + renderMethodToSet = 0; + } + Render.renderMethod = model.get(currentIndex).preferredRenderMethod; + Render.shadowsEnabled = model.get(currentIndex).shadowsEnabled; + renderingEffectsDropdown.displayText = model.get(currentIndex).text; + } + } + } + + Item { + Layout.preferredWidth: parent.width + Layout.preferredHeight: 35 + + HifiStylesUit.RalewayRegular { + id: refreshRateHeader + text: "Refresh Rate" + anchors.left: parent.left + anchors.top: parent.top + width: 130 + height: parent.height + size: 16 + color: "#FFFFFF" + } + + ListModel { + id: refreshRateModel + + ListElement { + text: "Economical" + refreshRatePreset: 0 // RefreshRateProfile::ECO + } + ListElement { + text: "Interactive" + refreshRatePreset: 1 // RefreshRateProfile::INTERACTIVE + } + ListElement { + text: "Real-Time" + refreshRatePreset: 2 // RefreshRateProfile::REALTIME + } + } + + HifiControlsUit.ComboBox { + id: refreshRateDropdown + enabled: performanceCustom.checked + anchors.left: refreshRateHeader.right + anchors.leftMargin: 20 + anchors.top: parent.top + width: 280 + height: parent.height + colorScheme: hifi.colorSchemes.dark + model: refreshRateModel + currentIndex: -1 + + function refreshRefreshRateDropdownDisplay() { + if (Performance.getRefreshRateProfile() === 0) { + refreshRateDropdown.currentIndex = 0; + } else if (Performance.getRefreshRateProfile() === 1) { + refreshRateDropdown.currentIndex = 1; + } else { + refreshRateDropdown.currentIndex = 2; + } + } + + Component.onCompleted: { + refreshRateDropdown.refreshRefreshRateDropdownDisplay(); + } + + onCurrentIndexChanged: { + Performance.setRefreshRateProfile(model.get(currentIndex).refreshRatePreset); + refreshRateDropdown.displayText = model.get(currentIndex).text; + } + } + } } } } + + function refreshAllDropdowns() { + worldDetailDropdown.refreshWorldDetailDropdown(); + renderingEffectsDropdown.refreshRenderingEffectsDropdownDisplay(); + refreshRateDropdown.refreshRefreshRateDropdownDisplay(); + } } diff --git a/interface/src/PerformanceManager.cpp b/interface/src/PerformanceManager.cpp index ec12ab0404..80c09e3fec 100644 --- a/interface/src/PerformanceManager.cpp +++ b/interface/src/PerformanceManager.cpp @@ -92,7 +92,7 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP RenderScriptingInterface::getInstance()->setShadowsEnabled(true); qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME); - DependencyManager::get()->setWorldDetailQuality(0.5f); + DependencyManager::get()->setWorldDetailQuality(0.75f); break; case PerformancePreset::MID: @@ -114,7 +114,7 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale); - DependencyManager::get()->setWorldDetailQuality(0.75f); + DependencyManager::get()->setWorldDetailQuality(0.25f); break; case PerformancePreset::UNKNOWN: diff --git a/interface/src/scripting/PlatformInfoScriptingInterface.cpp b/interface/src/scripting/PlatformInfoScriptingInterface.cpp index cbd94b3dd5..9adf514718 100644 --- a/interface/src/scripting/PlatformInfoScriptingInterface.cpp +++ b/interface/src/scripting/PlatformInfoScriptingInterface.cpp @@ -221,4 +221,6 @@ QStringList PlatformInfoScriptingInterface::getPlatformTierNames() { return platformTierNames; } - +bool PlatformInfoScriptingInterface::isRenderMethodDeferredCapable() { + return platform::Profiler::isRenderMethodDeferredCapable(); +} diff --git a/interface/src/scripting/PlatformInfoScriptingInterface.h b/interface/src/scripting/PlatformInfoScriptingInterface.h index 9ac67ec0bd..f59d476f0c 100644 --- a/interface/src/scripting/PlatformInfoScriptingInterface.h +++ b/interface/src/scripting/PlatformInfoScriptingInterface.h @@ -245,7 +245,12 @@ public slots: */ QStringList getPlatformTierNames(); - + /**jsdoc + * Gets whether the current hardware can render using the Deferred method. + * @function PlatformInfo.isRenderMethodDeferredCapable + * @returns {bool} true if the current hardware can render using the Deferred method; false otherwise. + */ + bool isRenderMethodDeferredCapable(); }; #endif // hifi_PlatformInfoScriptingInterface_h From 07c71cbadbc01dfd9a756b1f5b1e17b48d7179b3 Mon Sep 17 00:00:00 2001 From: PrestonB1123 Date: Thu, 11 Jul 2019 12:05:15 -0700 Subject: [PATCH 32/77] disabled P shortcut and re-enabled in metaverse --- interface/src/Application.cpp | 21 ------------------- .../keyboardShortcuts/keyboardShortcuts.js | 8 +++++++ 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b59fd223ba..a6f7e63247 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4429,27 +4429,6 @@ void Application::keyPressEvent(QKeyEvent* event) { } break; - case Qt::Key_P: { - if (!isShifted && !isMeta && !isOption && !event->isAutoRepeat()) { - AudioInjectorOptions options; - options.localOnly = true; - options.positionSet = false; // system sound - options.stereo = true; - - Setting::Handle notificationSounds{ MenuOption::NotificationSounds, true }; - Setting::Handle notificationSoundSnapshot{ MenuOption::NotificationSoundsSnapshot, true }; - if (notificationSounds.get() && notificationSoundSnapshot.get()) { - if (_snapshotSoundInjector) { - DependencyManager::get()->setOptionsAndRestart(_snapshotSoundInjector, options); - } else { - _snapshotSoundInjector = DependencyManager::get()->playSound(_snapshotSound, options); - } - } - takeSnapshot(true); - } - break; - } - case Qt::Key_Apostrophe: { if (isMeta) { auto cursor = Cursor::Manager::instance().getCursor(); diff --git a/scripts/system/keyboardShortcuts/keyboardShortcuts.js b/scripts/system/keyboardShortcuts/keyboardShortcuts.js index cf3927ac2d..165928d089 100644 --- a/scripts/system/keyboardShortcuts/keyboardShortcuts.js +++ b/scripts/system/keyboardShortcuts/keyboardShortcuts.js @@ -12,11 +12,19 @@ // (function () { // BEGIN LOCAL_SCOPE + var snapActivateSound = SoundCache.getSound(Script.resourcesPath() + "sounds/snapshot/snap.wav"); function keyPressEvent(event) { if (event.text.toUpperCase() === "B" && event.isControl) { Window.openWebBrowser(); } else if (event.text.toUpperCase() === "N" && event.isControl) { Users.toggleIgnoreRadius(); + } else if (event.text.toUpperCase() === "P") { + Audio.playSound(snapActivateSound, { + position: { x: MyAvatar.position.x, y: MyAvatar.position.y, z: MyAvatar.position.z }, + localOnly: true, + volume: 0.5 + }); + Window.takeSnapshot(true); } } From efccd10a65a9a4ae013a491b8ef31e0024a7314f Mon Sep 17 00:00:00 2001 From: amer cerkic Date: Thu, 11 Jul 2019 12:15:15 -0700 Subject: [PATCH 33/77] adding a destroy call to hmd scripting interface to ensure that it does not call isHmd mode on already dead display plugin. Also moved displayplugin reset below ui destroy calls to make sure it does not get called after its been destroyed --- interface/src/Application.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3085f1ed2a..3310454b8c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2772,7 +2772,8 @@ void Application::cleanupBeforeQuit() { DependencyManager::get()->removeAccountFromFile(); } - _displayPlugin.reset(); + DependencyManager::destroy(); + PluginManager::getInstance()->shutdown(); // Cleanup all overlays after the scripts, as scripts might add more @@ -2810,6 +2811,8 @@ void Application::cleanupBeforeQuit() { DependencyManager::destroy(); + _displayPlugin.reset(); + _snapshotSoundInjector = nullptr; // destroy Audio so it and its threads have a chance to go down safely From 22a7a97a9aadafd606b91081cfdb739aa5fd45bb Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 11 Jul 2019 12:23:04 -0700 Subject: [PATCH 34/77] fix forward web + parabola blending --- interface/src/raypick/ParabolaPointer.cpp | 6 ++---- libraries/render-utils/src/GeometryCache.cpp | 5 +---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/interface/src/raypick/ParabolaPointer.cpp b/interface/src/raypick/ParabolaPointer.cpp index 961ce627a4..0589124db8 100644 --- a/interface/src/raypick/ParabolaPointer.cpp +++ b/interface/src/raypick/ParabolaPointer.cpp @@ -405,7 +405,8 @@ gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabo using namespace shader::render_utils::program; static const std::vector> keys = { - std::make_tuple(false, false, parabola), std::make_tuple(false, true, parabola_forward), std::make_tuple(true, false, parabola_translucent) + std::make_tuple(false, false, parabola), std::make_tuple(false, true, parabola_forward), + std::make_tuple(true, false, parabola_translucent), std::make_tuple(true, true, parabola_forward) // The forward opaque/translucent pipelines are the same for now }; for (auto& key : keys) { @@ -423,9 +424,6 @@ gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabo _parabolaPipelines[{std::get<0>(key), std::get<1>(key)}] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state); } - - // The forward opaque/translucent pipelines are the same for now - _parabolaPipelines[{ true, true }] = _parabolaPipelines[{ false, true}]; } return _parabolaPipelines[{ _parabolaData.color.a < 1.0f, forward }]; } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 0553bb56a3..2bd656a664 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -2119,7 +2119,7 @@ gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent, bool using namespace shader::render_utils::program; static const std::vector> keys = { std::make_tuple(false, false, web_browser), std::make_tuple(false, true, web_browser_forward), - std::make_tuple(true, false, web_browser_translucent) + std::make_tuple(true, false, web_browser_translucent), std::make_tuple(true, true, web_browser_forward) // The forward opaque/translucent pipelines are the same for now }; for (auto& key : keys) { @@ -2134,9 +2134,6 @@ gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent, bool _webPipelines[{std::get<0>(key), std::get<1>(key)}] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state); } - - // The forward opaque/translucent pipelines are the same for now - _webPipelines[{ true, true }] = _webPipelines[{ false, true }]; } return _webPipelines[{ transparent, forward }]; From 7793e07eeb4693dc38dfb77600c8e96a42870d7b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 11 Jul 2019 13:34:58 -0700 Subject: [PATCH 35/77] fix polyvox --- libraries/entities-renderer/src/polyvox.slf | 3 +-- libraries/entities-renderer/src/polyvox.slv | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/polyvox.slf b/libraries/entities-renderer/src/polyvox.slf index f08728dbcb..3456823081 100644 --- a/libraries/entities-renderer/src/polyvox.slf +++ b/libraries/entities-renderer/src/polyvox.slf @@ -39,7 +39,6 @@ <@endif@> layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec3 _positionMS; layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; - layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normalMS; LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap; LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap; @@ -81,7 +80,7 @@ void main(void) { vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ)); vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY)); - vec3 normalMS = normalize(_normalMS); + vec3 normalMS = normalize(cross(dFdy(_positionMS.xyz), dFdx(_positionMS.xyz))); vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(normalMS.z); vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(normalMS.y); vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(normalMS.x); diff --git a/libraries/entities-renderer/src/polyvox.slv b/libraries/entities-renderer/src/polyvox.slv index 82ae741888..34547cef1a 100644 --- a/libraries/entities-renderer/src/polyvox.slv +++ b/libraries/entities-renderer/src/polyvox.slv @@ -24,7 +24,6 @@ <@endif@> layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec3 _positionMS; layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; - layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; <@endif@> void main(void) { @@ -41,7 +40,6 @@ void main(void) { <@endif@> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> - _normalMS = inNormal.xyz; _positionMS = inPosition.xyz; <@endif@> <@if HIFI_USE_FADE@> From f165184fb2c8b48bb004267bf74ec05c3ced569b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 11 Jul 2019 14:09:37 -0700 Subject: [PATCH 36/77] eliminate warnings about signed-vs-unsigned comparison --- libraries/workload/src/workload/View.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/workload/src/workload/View.cpp b/libraries/workload/src/workload/View.cpp index 4d7e610889..c083e0352c 100644 --- a/libraries/workload/src/workload/View.cpp +++ b/libraries/workload/src/workload/View.cpp @@ -46,7 +46,7 @@ void View::updateRegionsDefault(View& view) { float refFar = 10.0f; float refClose = 2.0f; - for (int i = 0; i < Region::NUM_TRACKED_REGIONS; i++) { + for (int i = 0; i < (int)Region::NUM_TRACKED_REGIONS; i++) { float weight = i + 1.0f; config[i * 2] = refClose; config[i * 2 + 1] = refFar * weight; @@ -56,13 +56,13 @@ void View::updateRegionsDefault(View& view) { } void View::updateRegionsFromBackFronts(View& view) { - for (int i = 0; i < Region::NUM_TRACKED_REGIONS; i++) { + for (int i = 0; i < (int)Region::NUM_TRACKED_REGIONS; i++) { view.regions[i] = evalRegionSphere(view, view.regionBackFronts[i].x, view.regionBackFronts[i].y); } } void View::updateRegionsFromBackFrontDistances(View& view, const float* configDistances) { - for (int i = 0; i < Region::NUM_TRACKED_REGIONS; i++) { + for (int i = 0; i < (int)Region::NUM_TRACKED_REGIONS; i++) { view.regionBackFronts[i] = glm::vec2(configDistances[i * 2], configDistances[i * 2 + 1]); } updateRegionsFromBackFronts(view); From 15e7663ed5b9fbdba5ea4b0423dfd335ce0284e1 Mon Sep 17 00:00:00 2001 From: amer cerkic Date: Thu, 11 Jul 2019 14:27:41 -0700 Subject: [PATCH 37/77] removing the destroy call since its not necessary --- interface/src/Application.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3310454b8c..abcafd5a3e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2772,8 +2772,6 @@ void Application::cleanupBeforeQuit() { DependencyManager::get()->removeAccountFromFile(); } - DependencyManager::destroy(); - PluginManager::getInstance()->shutdown(); // Cleanup all overlays after the scripts, as scripts might add more From 4c7d0fc6f423b01fb5ae8fafe79d3a08e70df97d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 11 Jul 2019 14:46:05 -0700 Subject: [PATCH 38/77] Updated layout --- .../dialogs/graphics/GraphicsSettings.qml | 115 +++++++++--------- 1 file changed, 59 insertions(+), 56 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml index 34f1caa737..d82ac47eb3 100644 --- a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml +++ b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml @@ -18,13 +18,11 @@ import controlsUit 1.0 as HifiControlsUit import "qrc:////qml//controls" as HifiControls import PerformanceEnums 1.0 -Flickable { +Item { HifiStylesUit.HifiConstants { id: hifi; } id: root; - contentWidth: parent.width - contentHeight: graphicsSettingsColumnLayout.height - clip: true + anchors.fill: parent ColumnLayout { id: graphicsSettingsColumnLayout @@ -38,13 +36,13 @@ Flickable { ColumnLayout { id: avatarNameTagsContainer Layout.preferredWidth: parent.width - Layout.topMargin: 38 + Layout.topMargin: 18 spacing: 0 HifiStylesUit.RalewayRegular { text: "GRAPHICS SETTINGS" Layout.maximumWidth: parent.width - height: paintedHeight + height: 30 size: 16 color: "#FFFFFF" } @@ -52,12 +50,12 @@ Flickable { ColumnLayout { Layout.topMargin: 10 Layout.preferredWidth: parent.width - Layout.preferredHeight: contentItem.height spacing: 0 HifiControlsUit.RadioButton { id: performanceLow colorScheme: hifi.colorSchemes.dark + height: 18 fontSize: 16 leftPadding: 0 text: "Low" @@ -71,6 +69,7 @@ Flickable { HifiControlsUit.RadioButton { id: performanceMedium colorScheme: hifi.colorSchemes.dark + height: 18 fontSize: 16 leftPadding: 0 text: "Medium" @@ -84,6 +83,7 @@ Flickable { HifiControlsUit.RadioButton { id: performanceHigh colorScheme: hifi.colorSchemes.dark + height: 18 fontSize: 16 leftPadding: 0 text: "High" @@ -97,6 +97,7 @@ Flickable { HifiControlsUit.RadioButton { id: performanceCustom colorScheme: hifi.colorSchemes.dark + height: 18 fontSize: 16 leftPadding: 0 text: "Custom" @@ -110,55 +111,7 @@ Flickable { ColumnLayout { Layout.topMargin: 10 Layout.preferredWidth: parent.width - Layout.preferredHeight: contentItem.height - spacing: 30 - - Item { - Layout.preferredWidth: parent.width - Layout.preferredHeight: 35 - - HifiStylesUit.RalewayRegular { - id: resolutionHeader - text: "Resolution Scale (" + Number.parseFloat(Render.viewportResolutionScale).toPrecision(3) + ")" - anchors.left: parent.left - anchors.top: parent.top - width: 130 - height: parent.height - size: 16 - color: "#FFFFFF" - } - - HifiControlsUit.Slider { - id: resolutionScaleSlider - enabled: performanceCustom.checked - anchors.left: resolutionHeader.right - anchors.leftMargin: 57 - anchors.top: parent.top - width: 150 - height: parent.height - colorScheme: hifi.colorSchemes.dark - minimumValue: 0.25 - maximumValue: 1.5 - stepSize: 0.02 - value: Render.viewportResolutionScale - live: true - - function updateResolutionScale(sliderValue) { - if (Render.viewportResolutionScale !== sliderValue) { - Render.viewportResolutionScale = sliderValue; - } - } - - onValueChanged: { - updateResolutionScale(value); - } - onPressedChanged: { - if (!pressed) { - updateResolutionScale(value); - } - } - } - } + spacing: 0 Item { Layout.preferredWidth: parent.width @@ -229,6 +182,7 @@ Flickable { Item { Layout.preferredWidth: parent.width Layout.preferredHeight: 35 + Layout.topMargin: 20 HifiStylesUit.RalewayRegular { id: renderingEffectsHeader @@ -303,6 +257,7 @@ Flickable { Item { Layout.preferredWidth: parent.width Layout.preferredHeight: 35 + Layout.topMargin: 20 HifiStylesUit.RalewayRegular { id: refreshRateHeader @@ -364,6 +319,54 @@ Flickable { } } } + + Item { + Layout.preferredWidth: parent.width + Layout.preferredHeight: 35 + Layout.topMargin: 16 + + HifiStylesUit.RalewayRegular { + id: resolutionHeader + text: "Resolution Scale (" + Number.parseFloat(Render.viewportResolutionScale).toPrecision(3) + ")" + anchors.left: parent.left + anchors.top: parent.top + width: 130 + height: parent.height + size: 16 + color: "#FFFFFF" + } + + HifiControlsUit.Slider { + id: resolutionScaleSlider + enabled: performanceCustom.checked + anchors.left: resolutionHeader.right + anchors.leftMargin: 57 + anchors.top: parent.top + width: 150 + height: parent.height + colorScheme: hifi.colorSchemes.dark + minimumValue: 0.25 + maximumValue: 1.5 + stepSize: 0.02 + value: Render.viewportResolutionScale + live: true + + function updateResolutionScale(sliderValue) { + if (Render.viewportResolutionScale !== sliderValue) { + Render.viewportResolutionScale = sliderValue; + } + } + + onValueChanged: { + updateResolutionScale(value); + } + onPressedChanged: { + if (!pressed) { + updateResolutionScale(value); + } + } + } + } } } } From 0d943ca55a2ddba4200958c0cd4d92a576fcc271 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 11 Jul 2019 14:47:31 -0700 Subject: [PATCH 39/77] more warning supression --- libraries/workload/src/workload/ViewTask.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 715b93618d..1c8e4d34b1 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -82,7 +82,7 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i ControlViews::ControlViews() { - for (int32_t i = 0; i < workload::Region::NUM_TRACKED_REGIONS; i++) { + for (uint32_t i = 0; i < workload::Region::NUM_TRACKED_REGIONS; i++) { regionBackFronts[i] = MIN_VIEW_BACK_FRONTS[i]; regionRegulators[i] = Regulator(std::chrono::milliseconds(2), MIN_VIEW_BACK_FRONTS[i], MAX_VIEW_BACK_FRONTS[i], glm::vec2(RELATIVE_STEP_DOWN), glm::vec2(RELATIVE_STEP_UP)); } @@ -166,7 +166,7 @@ glm::vec2 Regulator::clamp(const glm::vec2& backFront) const { void ControlViews::regulateViews(workload::Views& outViews, const workload::Timings& timings) { for (auto& outView : outViews) { - for (int32_t r = 0; r < workload::Region::NUM_TRACKED_REGIONS; r++) { + for (uint32_t r = 0; r < workload::Region::NUM_TRACKED_REGIONS; r++) { outView.regionBackFronts[r] = regionBackFronts[r]; } } @@ -198,13 +198,13 @@ void ControlViews::enforceRegionContainment() { // and each region should never exceed its min/max limits const glm::vec2 MIN_REGION_GAP = { 1.0f, 2.0f }; // enforce outside --> in - for (int32_t i = workload::Region::NUM_TRACKED_REGIONS - 2; i >= 0; --i) { + for (int32_t i = (int32_t)workload::Region::NUM_TRACKED_REGIONS - 2; i >= 0; --i) { int32_t j = i + 1; regionBackFronts[i] = regionRegulators[i].clamp(glm::min(regionBackFronts[i], regionBackFronts[j] - MIN_REGION_GAP)); } // enforce inside --> out - for (int32_t i = 1; i < workload::Region::NUM_TRACKED_REGIONS; ++i) { - int32_t j = i - 1; + for (uint32_t i = 1; i < workload::Region::NUM_TRACKED_REGIONS; ++i) { + uint32_t j = i - 1; regionBackFronts[i] = regionRegulators[i].clamp(glm::max(regionBackFronts[i], regionBackFronts[j] + MIN_REGION_GAP)); } } From 046b25ab67ecdeee8dc2276135afba24b7adb66c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 11 Jul 2019 14:56:17 -0700 Subject: [PATCH 40/77] fix haze on web entities, deferred and forward --- libraries/render-utils/src/GeometryCache.cpp | 16 +++--- .../src/render-utils/web_browser.slp | 2 +- libraries/render-utils/src/web_browser.slf | 50 +++++++++++++++---- libraries/render-utils/src/web_browser.slv | 10 ++-- 4 files changed, 56 insertions(+), 22 deletions(-) diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 2bd656a664..997f87b8d6 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -2117,22 +2117,24 @@ void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent, b gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent, bool forward) { if (_webPipelines.empty()) { using namespace shader::render_utils::program; - static const std::vector> keys = { - std::make_tuple(false, false, web_browser), std::make_tuple(false, true, web_browser_forward), - std::make_tuple(true, false, web_browser_translucent), std::make_tuple(true, true, web_browser_forward) // The forward opaque/translucent pipelines are the same for now - }; + const int NUM_WEB_PIPELINES = 4; + for (int i = 0; i < NUM_WEB_PIPELINES; ++i) { + bool transparent = i & 1; + bool forward = i & 2; + + // For any non-opaque or non-deferred pipeline, we use web_browser_forward + auto pipeline = (transparent || forward) ? web_browser_forward : web_browser; - for (auto& key : keys) { gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(true, true, gpu::LESS_EQUAL); // FIXME: do we need a testMaskDrawNoAA? PrepareStencil::testMaskDrawShapeNoAA(*state); - state->setBlendFunction(std::get<0>(key), + state->setBlendFunction(transparent, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); state->setCullMode(gpu::State::CULL_NONE); - _webPipelines[{std::get<0>(key), std::get<1>(key)}] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state); + _webPipelines[{ transparent, forward }] = gpu::Pipeline::create(gpu::Shader::createProgram(pipeline), state); } } diff --git a/libraries/render-utils/src/render-utils/web_browser.slp b/libraries/render-utils/src/render-utils/web_browser.slp index e9942be5cd..e283f4edcb 100644 --- a/libraries/render-utils/src/render-utils/web_browser.slp +++ b/libraries/render-utils/src/render-utils/web_browser.slp @@ -1 +1 @@ -DEFINES translucent:f/forward:f \ No newline at end of file +DEFINES forward \ No newline at end of file diff --git a/libraries/render-utils/src/web_browser.slf b/libraries/render-utils/src/web_browser.slf index 73745edf9e..f746916d3d 100644 --- a/libraries/render-utils/src/web_browser.slf +++ b/libraries/render-utils/src/web_browser.slf @@ -13,15 +13,27 @@ <@include gpu/Color.slh@> <@include render-utils/ShaderConstants.h@> -<@if not HIFI_USE_FORWARD@> - <@include DeferredBufferWrite.slh@> -<@else@> +<@if HIFI_USE_FORWARD@> + <@include LightingModel.slh@> + <@include graphics/Haze.slh@> + + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + + <@include graphics/Light.slh@> + <$declareLightBuffer()$> + layout(location=0) out vec4 _fragColor0; +<@else@> + <@include DeferredBufferWrite.slh@> <@endif@> LAYOUT(binding=0) uniform sampler2D webTexture; -<@if not HIFI_USE_FORWARD@> +<@if HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; + layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; +<@else@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; <@endif@> layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; @@ -34,13 +46,29 @@ void main(void) { texel = color_sRGBAToLinear(texel); texel *= _color; -<@if not HIFI_USE_FORWARD@> - <@if not HIFI_USE_TRANSLUCENT@> - packDeferredFragmentUnlit(normalize(_normalWS), 1.0, texel.rgb); - <@else@> - packDeferredFragmentTranslucent(normalize(_normalWS), texel.a, texel.rgb, DEFAULT_ROUGHNESS); - <@endif@> -<@else@> +<@if HIFI_USE_FORWARD@> _fragColor0 = texel; + + if (isHazeEnabled() > 0.0) { + // no light attenuation because we're unlit + + TransformCamera cam = getTransformCamera(); + + Light light = getKeyLight(); + vec3 lightDirectionWS = getLightDirection(light); + + if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + vec4 hazeColor = computeHazeColor( + _positionES.xyz, + _positionWS.xyz, + cam._viewInverse[3].xyz, + lightDirectionWS + ); + + _fragColor0.xyz = mix(_fragColor0.rgb, hazeColor.rgb, hazeColor.a); + } + } +<@else@> + packDeferredFragmentUnlit(normalize(_normalWS), 1.0, texel.rgb); <@endif@> } diff --git a/libraries/render-utils/src/web_browser.slv b/libraries/render-utils/src/web_browser.slv index d8da7d730b..07b4d7d3d7 100644 --- a/libraries/render-utils/src/web_browser.slv +++ b/libraries/render-utils/src/web_browser.slv @@ -17,7 +17,10 @@ <@include render-utils/ShaderConstants.h@> -<@if not HIFI_USE_FORWARD@> +<@if HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; + layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; +<@else@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; <@endif@> layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; @@ -29,9 +32,10 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); +<@if HIFI_USE_FORWARD@> + <$transformModelToWorldAndEyeAndClipPos(cam, obj, inPosition, _positionWS, _positionES, gl_Position)$> +<@else@> <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> - -<@if not HIFI_USE_FORWARD@> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> <@endif@> } \ No newline at end of file From 2f74f8253fc232a82ac903192933b75b0bcf7d5f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 11 Jul 2019 15:32:44 -0700 Subject: [PATCH 41/77] finishing requested changes --- interface/src/ui/InteractiveWindow.cpp | 167 +++++++++++++++++-------- interface/src/ui/InteractiveWindow.h | 18 ++- 2 files changed, 126 insertions(+), 59 deletions(-) diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index 84094a2500..2c580deb47 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -55,22 +55,96 @@ QmlWindowProxy::QmlWindowProxy(QObject* qmlObject, QObject* parent) : QmlWrapper _qmlWindow = qmlObject; } -void QmlWindowProxy::updateInteractiveWindowPositionForMode() { -} - void QmlWindowProxy::setPosition(const glm::vec2& position) { + if (_qmlWindow) { + _qmlWindow->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y)); + QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode"); + } } glm::vec2 QmlWindowProxy::getPosition() const { + if (!_qmlWindow) { + return {}; + } + + return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF()); } void QmlWindowProxy::setSize(const glm::vec2& size) { + if (_qmlWindow) { + _qmlWindow->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y)); + QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode"); + } } glm::vec2 QmlWindowProxy::getSize() const { + if (!_qmlWindow) { + return {}; + } + + return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize()); +} + +void QmlWindowProxy::setTitle(const QString& title) { + if (_qmlWindow) { + _qmlWindow->setProperty(TITLE_PROPERTY, title); + } +} + +QString QmlWindowProxy::getTitle() const { + if (!_qmlWindow) { + return QString(); + } + + return _qmlWindow->property(TITLE_PROPERTY).toString(); +} + +void QmlWindowProxy::setVisible(bool visible) { + if (_qmlWindow) { + _qmlWindow->setProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY, visible); + } +} + +bool QmlWindowProxy::isVisible() const { + if (!_qmlWindow) { + return false; + } + + return _qmlWindow->property(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool(); +} + +void QmlWindowProxy::setPresentationMode(int presentationMode) { + if (_qmlWindow) { + _qmlWindow->setProperty(PRESENTATION_MODE_PROPERTY, presentationMode); + } +} + +int QmlWindowProxy::getPresentationMode() const { + if (!_qmlWindow) { + return Virtual; + } + + return _qmlWindow->property(PRESENTATION_MODE_PROPERTY).toInt(); +} + +void QmlWindowProxy::parentNativeWindowToMainWindow() { +#ifdef Q_OS_WIN + if (!_qmlWindow) { + return; + } + const auto nativeWindowProperty = _qmlWindow->property("nativeWindow"); + if (nativeWindowProperty.isNull() || !nativeWindowProperty.isValid()) { + return; + } + const auto nativeWindow = qvariant_cast(nativeWindowProperty); + SetWindowLongPtr((HWND)nativeWindow->winId(), GWLP_HWNDPARENT, (LONG)MainWindow::findMainWindow()->winId()); +#endif +} + +static void qmlWindowProxyDeleter(QmlWindowProxy* qmlWindowProxy) { + qmlWindowProxy->deleteLater(); } -void QmlWindowProxy::setTitle(const QString& title static void dockWidgetDeleter(DockWidget* dockWidget) { dockWidget->deleteLater(); } @@ -201,7 +275,7 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap auto offscreenUi = DependencyManager::get(); // Build the event bridge and wrapper on the main thread offscreenUi->loadInNewContext(CONTENT_WINDOW_QML, [&](QQmlContext* context, QObject* object) { - _qmlWindow = object; + _qmlWindowProxy = std::shared_ptr(new QmlWindowProxy(object, nullptr), qmlWindowProxyDeleter); context->setContextProperty(EVENT_BRIDGE_PROPERTY, this); if (properties.contains(ADDITIONAL_FLAGS_PROPERTY)) { object->setProperty(ADDITIONAL_FLAGS_PROPERTY, properties[ADDITIONAL_FLAGS_PROPERTY].toUInt()); @@ -268,7 +342,7 @@ void InteractiveWindow::sendToQml(const QVariant& message) { QMetaObject::invokeMethod(rootItem, "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message)); } } else { - QMetaObject::invokeMethod(_qmlWindow, "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message)); + QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message)); } } @@ -281,8 +355,12 @@ void InteractiveWindow::emitWebEvent(const QVariant& webMessage) { } void InteractiveWindow::close() { - if (_qmlWindow) { - _qmlWindow->deleteLater(); + if (_qmlWindowProxy) { + QObject* qmlWindow = _qmlWindowProxy->getQmlWindow(); + if (qmlWindow) { + qmlWindow->deleteLater(); + } + _qmlWindowProxy->deleteLater(); } if (_dockWidget) { @@ -290,18 +368,18 @@ void InteractiveWindow::close() { BLOCKING_INVOKE_METHOD(window, "removeDockWidget", Q_ARG(QDockWidget*, _dockWidget.get())); } _dockWidget = nullptr; - _qmlWindow = nullptr; + _qmlWindowProxy = nullptr; } void InteractiveWindow::show() { - if (_qmlWindow) { - QMetaObject::invokeMethod(_qmlWindow, "show"); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "show"); } } void InteractiveWindow::raise() { - if (_qmlWindow) { - QMetaObject::invokeMethod(_qmlWindow, "raiseWindow"); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "raiseWindow"); } } @@ -316,93 +394,74 @@ void InteractiveWindow::qmlToScript(const QVariant& message) { } void InteractiveWindow::setVisible(bool visible) { - if (!_qmlWindow.isNull()) { - QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_VISIBLE_PROPERTY), - Q_ARG(bool, visible)); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setVisible", Q_ARG(bool, visible)); } } bool InteractiveWindow::isVisible() const { - if (_qmlWindow.isNull()) { + if (!_qmlWindowProxy) { return false; } - return _qmlWindow->property(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool(); + return _qmlWindowProxy->isVisible(); } glm::vec2 InteractiveWindow::getPosition() const { - if (_qmlWindow.isNull()) { + if (!_qmlWindowProxy) { return {}; } - return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF()); + return _qmlWindowProxy->getPosition(); } void InteractiveWindow::setPosition(const glm::vec2& position) { - if (!_qmlWindow.isNull()) { - QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_POSITION_PROPERTY), - Q_ARG(QPointF, QPointF(position.x, position.y))); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode"); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setPosition", Q_ARG(const glm::vec2&, position)); } } glm::vec2 InteractiveWindow::getSize() const { - if (_qmlWindow.isNull()) { + if (!_qmlWindowProxy) { return {}; } - return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize()); + return _qmlWindowProxy->getSize(); } void InteractiveWindow::setSize(const glm::vec2& size) { - if (!_qmlWindow.isNull()) { - QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, INTERACTIVE_WINDOW_SIZE_PROPERTY), - Q_ARG(QSize, QSize(size.x, size.y))); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode"); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setSize", Q_ARG(const glm::vec2&, size)); } } QString InteractiveWindow::getTitle() const { - if (_qmlWindow.isNull()) { + if (!_qmlWindowProxy) { return QString(); } - return _qmlWindow->property(TITLE_PROPERTY).toString(); + return _qmlWindowProxy->getTitle(); } void InteractiveWindow::setTitle(const QString& title) { - if (!_qmlWindow.isNull()) { - QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, TITLE_PROPERTY), - Q_ARG(QString, title)); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setTitle", Q_ARG(const QString&, title)); } } int InteractiveWindow::getPresentationMode() const { - if (_qmlWindow.isNull()) { + if (!_qmlWindowProxy) { return Virtual; } - return _qmlWindow->property(PRESENTATION_MODE_PROPERTY).toInt(); + return _qmlWindowProxy->getPresentationMode(); } void InteractiveWindow::parentNativeWindowToMainWindow() { -#ifdef Q_OS_WIN - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "parentNativeWindowToMainWindow"); - return; + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "parentNativeWindowToMainWindow"); } - if (_qmlWindow.isNull()) { - return; - } - const auto nativeWindowProperty = _qmlWindow->property("nativeWindow"); - if (nativeWindowProperty.isNull() || !nativeWindowProperty.isValid()) { - return; - } - const auto nativeWindow = qvariant_cast(nativeWindowProperty); - SetWindowLongPtr((HWND)nativeWindow->winId(), GWLP_HWNDPARENT, (LONG)MainWindow::findMainWindow()->winId()); -#endif } void InteractiveWindow::setPresentationMode(int presentationMode) { - if (!_qmlWindow.isNull()) { - QMetaObject::invokeMethod(_qmlWindow, "setProperty", Q_ARG(const char*, PRESENTATION_MODE_PROPERTY), - Q_ARG(int, presentationMode)); + if (_qmlWindowProxy) { + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setPresentationMode", Q_ARG(int, presentationMode)); } } diff --git a/interface/src/ui/InteractiveWindow.h b/interface/src/ui/InteractiveWindow.h index d9886bd138..7abdc5210a 100644 --- a/interface/src/ui/InteractiveWindow.h +++ b/interface/src/ui/InteractiveWindow.h @@ -23,22 +23,30 @@ #include #include -class QmlWindowProxy : QmlWrapper { +class QmlWindowProxy : public QmlWrapper { Q_OBJECT public: QmlWindowProxy(QObject* qmlObject, QObject* parent = nullptr); - Q_INVOKABLE void updateInteractiveWindowPositionForMode(); - Q_INVOKABLE void setPosition(const glm::vec2& position); - glm::vec2 getPositiion() const; + glm::vec2 getPosition() const; Q_INVOKABLE void setSize(const glm::vec2& size); glm::vec2 getSize() const; Q_INVOKABLE void setTitle(const QString& title); QString getTitle() const; + + Q_INVOKABLE void setVisible(bool visible); + bool isVisible() const; + + Q_INVOKABLE void setPresentationMode(int presentationMode); + int getPresentationMode() const; + + Q_INVOKABLE void parentNativeWindowToMainWindow(); + + QObject* getQmlWindow() const { return _qmlWindow; } private: QObject* _qmlWindow; @@ -314,7 +322,7 @@ protected slots: void forwardKeyReleaseEvent(int key, int modifiers); private: - QPointer _qmlWindow; + std::shared_ptr _qmlWindowProxy; std::shared_ptr _dockWidget { nullptr }; }; From 56a55efbb3fc8e920eebaa94065027ef48088e33 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 11 Jul 2019 16:12:40 -0700 Subject: [PATCH 42/77] Fix a quick renderer bug --- .../resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml index d82ac47eb3..88709c8be7 100644 --- a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml +++ b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml @@ -247,7 +247,7 @@ Item { PlatformInfo.isRenderMethodDeferredCapable()) { renderMethodToSet = 0; } - Render.renderMethod = model.get(currentIndex).preferredRenderMethod; + Render.renderMethod = renderMethodToSet; Render.shadowsEnabled = model.get(currentIndex).shadowsEnabled; renderingEffectsDropdown.displayText = model.get(currentIndex).text; } From bda87aa13ff93826050161e55f6f3193bb9472c2 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 11 Jul 2019 16:32:35 -0700 Subject: [PATCH 43/77] trying to fix android --- cmake/macros/AutoScribeShader.cmake | 17 +++++++++-------- libraries/entities-renderer/src/paintStroke.slv | 3 --- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake index f0f1fe1d05..20aa334134 100755 --- a/cmake/macros/AutoScribeShader.cmake +++ b/cmake/macros/AutoScribeShader.cmake @@ -316,10 +316,11 @@ macro(AUTOSCRIBE_SHADER_LIB) if (HAS_FRAGMENT EQUAL -1) set(DEFINES "${VERTEX_DEFINES}") set(SHADER_LIST "") - unset(SHADER_FILE) - unset(SHADER_FILE CACHE) - find_file(SHADER_FILE "${VERTEX_NAME}.slv" PATHS "${PROGRAM_FOLDER}" PATH_SUFFIXES "..") - message("boop ${SHADER_FILE} ${VERTEX_NAME} ${PROGRAM_FOLDER}") + set(SHADER_FILE "${PROGRAM_FOLDER}/${VERTEX_NAME}.slv") + if (NOT EXISTS "${SHADER_FILE}") + set(SHADER_FILE "${PROGRAM_FOLDER}/../${VERTEX_NAME}.slv") + endif() + find_file(SHADER_FILE "" PATHS "${PROGRAM_FOLDER}" PATH_SUFFIXES ".." NO_DEFAULT_PATH) AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) string(CONCAT VERTEX_ENUMS "${VERTEX_ENUMS}" "${SHADER_LIST}") else() @@ -335,10 +336,10 @@ macro(AUTOSCRIBE_SHADER_LIB) if (HAS_VERTEX EQUAL -1) set(DEFINES "${FRAGMENT_DEFINES}") set(SHADER_LIST "") - unset(SHADER_FILE) - unset(SHADER_FILE CACHE) - find_file(SHADER_FILE "${FRAGMENT_NAME}.slf" PATHS "${PROGRAM_FOLDER}" PATH_SUFFIXES "..") - message("boop2 ${SHADER_FILE} ${FRAGMENT_NAME} ${PROGRAM_FOLDER}") + set(SHADER_FILE "${PROGRAM_FOLDER}/${FRAGMENT_NAME}.slf") + if (NOT EXISTS "${SHADER_FILE}") + set(SHADER_FILE "${PROGRAM_FOLDER}/../${FRAGMENT_NAME}.slf") + endif() AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) string(CONCAT FRAGMENT_ENUMS "${FRAGMENT_ENUMS}" "${SHADER_LIST}") else() diff --git a/libraries/entities-renderer/src/paintStroke.slv b/libraries/entities-renderer/src/paintStroke.slv index 2a2025e59f..9a44223dd4 100644 --- a/libraries/entities-renderer/src/paintStroke.slv +++ b/libraries/entities-renderer/src/paintStroke.slv @@ -3,9 +3,6 @@ // <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // -// paintStroke.vert -// vertex shader -// // Created by Eric Levin on 7/20/15. // Copyright 2014 High Fidelity, Inc. // From cc7214fca3176de2b39fd16789eca0773ff0ec5f Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 11 Jul 2019 16:56:35 -0700 Subject: [PATCH 44/77] cleanup --- interface/src/Application.cpp | 6 ------ interface/src/MacHelper.cpp | 27 ++++++++++++++------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 449e27b689..67333da9b7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2836,20 +2836,17 @@ void Application::cleanupBeforeQuit() { } Application::~Application() { - qCInfo(interfaceapp) << "HRS FIXME Quit 1"; // remove avatars from physics engine auto avatarManager = DependencyManager::get(); avatarManager->clearOtherAvatars(); auto myCharacterController = getMyAvatar()->getCharacterController(); myCharacterController->clearDetailedMotionStates(); - qCInfo(interfaceapp) << "HRS FIXME Quit 2"; PhysicsEngine::Transaction transaction; avatarManager->buildPhysicsTransaction(transaction); _physicsEngine->processTransaction(transaction); avatarManager->handleProcessedPhysicsTransaction(transaction); avatarManager->deleteAllAvatars(); - qCInfo(interfaceapp) << "HRS FIXME Quit 3"; _physicsEngine->setCharacterController(nullptr); @@ -2860,12 +2857,9 @@ Application::~Application() { // shutdown graphics engine _graphicsEngine.shutdown(); - qCInfo(interfaceapp) << "HRS FIXME Quit 4"; _gameWorkload.shutdown(); - qCInfo(interfaceapp) << "HRS FIXME Quit 5"; DependencyManager::destroy(); - qCInfo(interfaceapp) << "HRS FIXME Quit 6"; #ifdef Q_OS_MAC DependencyManager::destroy(); #endif diff --git a/interface/src/MacHelper.cpp b/interface/src/MacHelper.cpp index f6b76649cd..b3513afdc9 100755 --- a/interface/src/MacHelper.cpp +++ b/interface/src/MacHelper.cpp @@ -11,32 +11,34 @@ #include "InterfaceLogging.h" #include "MacHelper.h" +#include #ifdef Q_OS_MAC -#include #include - -io_connect_t root_port; -IONotificationPortRef notifyPortRef; -io_object_t notifierObject; -void* refCon; +#include -void sleepHandler(void* refCon, io_service_t service, natural_t messageType, void* messageArgument) { - qCInfo(interfaceapp) << "HRS FIXME sleepHandler."; +// These type definitions come from IOKit, which includes a definition of Duration that conflicts with ours. +// So... we include these definitions here rather than in the .h, as the .h is included in Application.cpp which +// uses Duration. +static io_connect_t root_port; +static IONotificationPortRef notifyPortRef; +static io_object_t notifierObject; +static void* refCon; + +static void sleepHandler(void* refCon, io_service_t service, natural_t messageType, void* messageArgument) { if (messageType == kIOMessageSystemHasPoweredOn) { - qCInfo(interfaceapp) << "HRS FIXME Waking up from sleep or hybernation."; + qCInfo(interfaceapp) << "Waking up from sleep or hybernation."; + QMetaObject::invokeMethod(DependencyManager::get().data(), "noteAwakening", Qt::QueuedConnection); } } #endif MacHelper::MacHelper() { - qCInfo(interfaceapp) << "HRS FIXME Start MacHelper."; #ifdef Q_OS_MAC root_port = IORegisterForSystemPower(refCon, ¬ifyPortRef, sleepHandler, ¬ifierObject); if (root_port == 0) { qCWarning(interfaceapp) << "IORegisterForSystemPower failed"; - } else { - qCDebug(interfaceapp) << "HRS FIXME IORegisterForSystemPower OK"; + return; } CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), @@ -45,7 +47,6 @@ MacHelper::MacHelper() { } MacHelper::~MacHelper() { - qCInfo(interfaceapp) << "HRS FIXME End MacHelper."; #ifdef Q_OS_MAC CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), From 590876e54bcae8e51f1bf502761d9503529f0d79 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 11 Jul 2019 17:05:32 -0700 Subject: [PATCH 45/77] remove NUM_REGIONS_TRACKED --- libraries/workload/src/workload/RegionState.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libraries/workload/src/workload/RegionState.h b/libraries/workload/src/workload/RegionState.h index d941a5046c..ce74f7adaa 100644 --- a/libraries/workload/src/workload/RegionState.h +++ b/libraries/workload/src/workload/RegionState.h @@ -53,12 +53,7 @@ namespace workload { using Inputs = IndexVectors; using JobModel = workload::Job::ModelI; - // we track Proxies in regions R1 through R3 - const uint32_t NUM_REGIONS_TRACKED = uint32_t(Region::R3 - Region::R1 + 1); - - RegionState() { - _state.resize(NUM_REGIONS_TRACKED); - } + RegionState() { _state.resize(workload::Region::NUM_TRACKED_REGIONS); } void configure(const Config& config); void run(const workload::WorkloadContextPointer& renderContext, const Inputs& inputs); From 9baf4c7078150d081b018032e1b382d23189d0df Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 31 Jan 2019 11:22:26 -0800 Subject: [PATCH 46/77] comfort mode -- squeeze vision to avoid sickness --- interface/src/Application.cpp | 6 + interface/src/Application.h | 7 + interface/src/VisionSqueeze.cpp | 213 ++++++++++++++++++ interface/src/VisionSqueeze.h | 108 +++++++++ interface/src/avatar/MyAvatar.cpp | 1 - .../src/scripting/HMDScriptingInterface.cpp | 80 +++++++ .../src/scripting/HMDScriptingInterface.h | 32 +++ interface/src/ui/PreferencesDialog.cpp | 28 +++ .../DrawTextureWithVisionSqueeze.slf | 104 +++++++++ .../DrawTextureWithVisionSqueeze.slp | 1 + .../display-plugins/OpenGLDisplayPlugin.cpp | 11 +- .../src/display-plugins/OpenGLDisplayPlugin.h | 2 + .../src/display-plugins/VisionSqueeze.slh | 106 +++++++++ .../display-plugins/hmd/HmdDisplayPlugin.cpp | 61 ++++- .../display-plugins/hmd/HmdDisplayPlugin.h | 34 ++- libraries/gpu/src/gpu/Context.cpp | 2 +- libraries/plugins/src/plugins/DisplayPlugin.h | 3 + libraries/render/src/render/Args.h | 7 + plugins/oculus/src/OculusDisplayPlugin.cpp | 12 +- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 25 +- plugins/openvr/src/OpenVrDisplayPlugin.h | 11 + 21 files changed, 846 insertions(+), 8 deletions(-) create mode 100644 interface/src/VisionSqueeze.cpp create mode 100644 interface/src/VisionSqueeze.h create mode 100644 libraries/display-plugins/src/display-plugins/DrawTextureWithVisionSqueeze.slf create mode 100644 libraries/display-plugins/src/display-plugins/DrawTextureWithVisionSqueeze.slp create mode 100644 libraries/display-plugins/src/display-plugins/VisionSqueeze.slh diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a6f7e63247..59b55fe22f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6755,6 +6755,12 @@ void Application::update(float deltaTime) { if (!getActiveDisplayPlugin()->isActive()) { getMain3DScene()->processTransactionQueue(); } + + // decide if the sensorToWorldMatrix is changing in a way that warrents squeezing the edges of the view down + if (getActiveDisplayPlugin()->isHmd()) { + PerformanceTimer perfTimer("squeezeVision"); + _visionSqueeze.updateVisionSqueeze(myAvatar->getSensorToWorldMatrix(), deltaTime); + } } void Application::updateRenderArgs(float deltaTime) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 2d6821bbd9..1e7180e203 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -78,6 +78,7 @@ #include #include "Sound.h" +#include "VisionSqueeze.h" class GLCanvas; class FaceTracker; @@ -364,6 +365,9 @@ public: void forceLoginWithTokens(const QString& tokens); void setConfigFileURL(const QString& fileUrl); + // used by preferences and HMDScriptingInterface... + VisionSqueeze& getVisionSqueeze() { return _visionSqueeze; } + signals: void svoImportRequested(const QString& url); @@ -731,6 +735,7 @@ private: bool _loginDialogPoppedUp{ false }; bool _desktopRootItemCreated{ false }; + bool _developerMenuVisible{ false }; QString _previousAvatarSkeletonModel; float _previousAvatarTargetScale; @@ -837,5 +842,7 @@ private: bool _resumeAfterLoginDialogActionTaken_SafeToRun { false }; bool _startUpFinished { false }; bool _overrideEntry { false }; + + VisionSqueeze _visionSqueeze; }; #endif // hifi_Application_h diff --git a/interface/src/VisionSqueeze.cpp b/interface/src/VisionSqueeze.cpp new file mode 100644 index 0000000000..cb895cc74f --- /dev/null +++ b/interface/src/VisionSqueeze.cpp @@ -0,0 +1,213 @@ +// +// VisionSqueeze.cpp +// interface/src +// +// Created by Seth Alves on 2019-3-13. +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "VisionSqueeze.h" + +#include +#include + +#include + +#include "Application.h" + +VisionSqueeze::VisionSqueeze() : + _visionSqueezeEnabled(_visionSqueezeEnabledSetting.get()), + _visionSqueezeRatioX(_visionSqueezeRatioXSetting.get()), + _visionSqueezeRatioY(_visionSqueezeRatioYSetting.get()), + _visionSqueezeUnSqueezeDelay(_visionSqueezeUnSqueezeDelaySetting.get()), + _visionSqueezeUnSqueezeSpeed(_visionSqueezeUnSqueezeSpeedSetting.get()), + _visionSqueezeTransition(_visionSqueezeTransitionSetting.get()), + _visionSqueezePerEye(_visionSqueezePerEyeSetting.get()), + _visionSqueezeGroundPlaneY(_visionSqueezeGroundPlaneYSetting.get()), + _visionSqueezeSpotlightSize(_visionSqueezeSpotlightSizeSetting.get()), + _visionSqueezeTurningXFactor(_visionSqueezeTurningXFactorSetting.get()), + _visionSqueezeTurningYFactor(_visionSqueezeTurningYFactorSetting.get()) { +} + +void VisionSqueeze::setVisionSqueezeEnabled(bool value) { + if (value != _visionSqueezeEnabled) { + _visionSqueezeEnabled = value; + _visionSqueezeEnabledSetting.set(_visionSqueezeEnabled); + } +} + +void VisionSqueeze::setVisionSqueezeRatioX(float value) { + if (value != _visionSqueezeRatioX) { + _visionSqueezeRatioX = value; + _visionSqueezeRatioXSetting.set(_visionSqueezeRatioX); + } +} + +void VisionSqueeze::setVisionSqueezeRatioY(float value) { + if (value != _visionSqueezeRatioY) { + _visionSqueezeRatioY = value; + _visionSqueezeRatioYSetting.set(_visionSqueezeRatioY); + } +} + +void VisionSqueeze::setVisionSqueezeUnSqueezeDelay(float value) { + if (value != _visionSqueezeUnSqueezeDelay) { + _visionSqueezeUnSqueezeDelay = value; + _visionSqueezeUnSqueezeDelaySetting.set(_visionSqueezeUnSqueezeDelay); + } +} + +void VisionSqueeze::setVisionSqueezeUnSqueezeSpeed(float value) { + if (value != _visionSqueezeUnSqueezeSpeed) { + _visionSqueezeUnSqueezeSpeed = value; + _visionSqueezeUnSqueezeSpeedSetting.set(_visionSqueezeUnSqueezeSpeed); + } +} + +void VisionSqueeze::setVisionSqueezeTransition(float value) { + if (value != _visionSqueezeTransition) { + _visionSqueezeTransition = value; + _visionSqueezeTransitionSetting.set(_visionSqueezeTransition); + } +} + +void VisionSqueeze::setVisionSqueezePerEye(int value) { + if (value != _visionSqueezePerEye) { + _visionSqueezePerEye = value; + _visionSqueezePerEyeSetting.set(_visionSqueezePerEye); + } +} + +void VisionSqueeze::setVisionSqueezeGroundPlaneY(float value) { + if (value != _visionSqueezeGroundPlaneY) { + _visionSqueezeGroundPlaneY = value; + _visionSqueezeGroundPlaneYSetting.set(_visionSqueezeGroundPlaneY); + } +} + +void VisionSqueeze::setVisionSqueezeSpotlightSize(float value) { + if (value != _visionSqueezeSpotlightSize) { + _visionSqueezeSpotlightSize = value; + _visionSqueezeSpotlightSizeSetting.set(_visionSqueezeSpotlightSize); + } +} + +void VisionSqueeze::setVisionSqueezeTurningXFactor(float value) { + if (value != _visionSqueezeTurningXFactor) { + _visionSqueezeTurningXFactor = value; + _visionSqueezeTurningXFactorSetting.set(_visionSqueezeTurningXFactor); + } +} + +void VisionSqueeze::setVisionSqueezeTurningYFactor(float value) { + if (value != _visionSqueezeTurningYFactor) { + _visionSqueezeTurningYFactor = value; + _visionSqueezeTurningYFactorSetting.set(_visionSqueezeTurningYFactor); + } +} + +void VisionSqueeze::updateVisionSqueeze(const glm::mat4& sensorToWorldMatrix, float deltaTime) { + + const float SENSOR_TO_WORLD_TRANS_EPSILON = 0.0001f; + const float SENSOR_TO_WORLD_TRANS_Y_EPSILON = 0.01f; + const float SENSOR_TO_WORLD_TRANS_ITS_A_TELEPORT_SQUARED = 2.0f; + const float SENSOR_TO_WORLD_ROT_EPSILON = 0.000005f; + const float SENSOR_TO_WORLD_ROT_ITS_A_SNAP_TURN = 0.99f; + const float VISION_SQUEEZE_TP_LOCKOUT = 0.1f; // seconds + + glm::vec3 scale; + glm::quat rotation; + glm::vec3 translation; + glm::vec3 skew; + glm::vec4 perspective; + glm::decompose(sensorToWorldMatrix, scale, rotation, translation, skew, perspective); + + if (!_visionSqueezeEnabled) { + _squeezeVision = false; + _squeezeVisionTurning = false; + } else if (_visionSqueezeLockout > 0.0f) { + _visionSqueezeLockout -= deltaTime; + } else { + _squeezeVision = false; + _squeezeVisionTurning = false; + glm::vec3 absTransDelta = glm::abs(translation - _prevTranslation); + float rotDot = fabsf(glm::dot(rotation, _prevRotation)); + + // if the avatar has just teleported or snap-turned, briefly disable triggering of vision-squeeze + if (glm::length2(translation - _prevTranslation) > SENSOR_TO_WORLD_TRANS_ITS_A_TELEPORT_SQUARED || + rotDot < SENSOR_TO_WORLD_ROT_ITS_A_SNAP_TURN) { + _visionSqueezeLockout = VISION_SQUEEZE_TP_LOCKOUT; + _squeezeVision = true; + _squeezeVisionTurning = true; + } else if (rotDot < 1.0f - SENSOR_TO_WORLD_ROT_EPSILON) { + _squeezeVision = true; + _squeezeVisionTurning = true; + } else if (absTransDelta.x > SENSOR_TO_WORLD_TRANS_EPSILON || + absTransDelta.y > SENSOR_TO_WORLD_TRANS_Y_EPSILON || + absTransDelta.z > SENSOR_TO_WORLD_TRANS_EPSILON) { + _squeezeVision = true; + _squeezeVisionTurning = false; + } + } + + _prevTranslation = translation; + _prevRotation = rotation; + + static quint64 lastSqueezeTime = 0; + quint64 now = usecTimestampNow(); + static float visionSqueezeX = 0.0f; // 0.0 -- unobstructed, 1.0 -- fully blocked + static float visionSqueezeY = 0.0f; // 0.0 -- unobstructed, 1.0 -- fully blocked + + if (_squeezeVision) { + float ratioX = getVisionSqueezeRatioX(); + float ratioY = getVisionSqueezeRatioY(); + + if (ratioX >= 0.0f) { + if (_squeezeVisionTurning) { + ratioX += (1.0f - ratioX) * getVisionSqueezeTurningXFactor(); + } + float newVisionSqueezeX = ratioX; + if (newVisionSqueezeX >= visionSqueezeX) { + lastSqueezeTime = now; + visionSqueezeX = newVisionSqueezeX; + } + } else { + visionSqueezeX = -1.0f; + } + + if (ratioY >= 0.0f) { + float newVisionSqueezeY = ratioY; + if (newVisionSqueezeY >= visionSqueezeY) { + lastSqueezeTime = now; + visionSqueezeY = newVisionSqueezeY; + } + } else { + visionSqueezeY = -1.0f; + } + } + + float unsqueezeAmount = deltaTime * getVisionSqueezeUnSqueezeSpeed(); + if (now - lastSqueezeTime > getVisionSqueezeUnSqueezeDelay() * USECS_PER_SECOND) { + visionSqueezeX -= unsqueezeAmount; + if (visionSqueezeX < 0.0f) { + visionSqueezeX = -1.0f; + } + visionSqueezeY -= unsqueezeAmount; + if (visionSqueezeY < 0.0f) { + visionSqueezeY = -1.0f; + } + } + + std::shared_ptr hmdDisplayPlugin = + std::dynamic_pointer_cast(qApp->getActiveDisplayPlugin()); + if (hmdDisplayPlugin) { + hmdDisplayPlugin->updateVisionSqueezeParameters(visionSqueezeX, visionSqueezeY, + getVisionSqueezeTransition(), + getVisionSqueezePerEye(), + getVisionSqueezeGroundPlaneY(), + getVisionSqueezeSpotlightSize()); + } +} diff --git a/interface/src/VisionSqueeze.h b/interface/src/VisionSqueeze.h new file mode 100644 index 0000000000..d32f608ed0 --- /dev/null +++ b/interface/src/VisionSqueeze.h @@ -0,0 +1,108 @@ +// +// VisionSqueeze.h +// interface/src +// +// Created by Seth Alves on 2019-3-13. +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_VisionSqueeze_h +#define hifi_VisionSqueeze_h + +#include +#include + +#include + +static const float DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR = 0.51f; +static const float DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR = 0.36f; +static const float DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY = 0.2f; // seconds +static const float DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED = 3.0f; +static const float DEFAULT_VISION_SQUEEZE_TRANSITION = 0.25f; +static const int DEFAULT_VISION_SQUEEZE_PER_EYE = 1; +static const float DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y = 0.0f; +static const float DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE = 6.0f; + + +class VisionSqueeze { + +public: + + VisionSqueeze(); + + bool getVisionSqueezeEnabled() const { return _visionSqueezeEnabled; } + void setVisionSqueezeEnabled(bool value); + float getVisionSqueezeRatioX() const { return _visionSqueezeRatioX; } + float getVisionSqueezeRatioY() const { return _visionSqueezeRatioY; } + void setVisionSqueezeRatioX(float value); + void setVisionSqueezeRatioY(float value); + float getVisionSqueezeUnSqueezeDelay() const { return _visionSqueezeUnSqueezeDelay; } + void setVisionSqueezeUnSqueezeDelay(float value); + float getVisionSqueezeUnSqueezeSpeed() const { return _visionSqueezeUnSqueezeSpeed; } + void setVisionSqueezeUnSqueezeSpeed(float value); + float getVisionSqueezeTransition() const { return _visionSqueezeTransition; } + void setVisionSqueezeTransition(float value); + int getVisionSqueezePerEye() const { return _visionSqueezePerEye; } + void setVisionSqueezePerEye(int value); + float getVisionSqueezeGroundPlaneY() const { return _visionSqueezeGroundPlaneY; } + void setVisionSqueezeGroundPlaneY(float value); + float getVisionSqueezeSpotlightSize() const { return _visionSqueezeSpotlightSize; } + void setVisionSqueezeSpotlightSize(float value); + float getVisionSqueezeTurningXFactor() const { return _visionSqueezeTurningXFactor; } + void setVisionSqueezeTurningXFactor(float value); + float getVisionSqueezeTurningYFactor() const { return _visionSqueezeTurningYFactor; } + void setVisionSqueezeTurningYFactor(float value); + + void updateVisionSqueeze(const glm::mat4& sensorToWorldMatrix, float deltaTime); + + // state variable accessors used by Application.cpp... + bool getSqueezeVision() const { return _squeezeVision; } + void setSqueezeVision(bool value) { _squeezeVision = value; } + bool getSqueezeVisionTurning() const { return _squeezeVisionTurning; } + void setSqueezeVisionTurning(bool value) { _squeezeVisionTurning = value; } + +private: + Setting::Handle _visionSqueezeEnabledSetting {"visionSqueezeEnabled", false}; + Setting::Handle _visionSqueezeRatioXSetting {"visionSqueezeRatioX", 0.0f}; + Setting::Handle _visionSqueezeRatioYSetting {"visionSqueezeRatioY", 0.0f}; + Setting::Handle _visionSqueezeUnSqueezeDelaySetting {"visionSqueezeUnSqueezeDelay", + DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY}; + Setting::Handle _visionSqueezeUnSqueezeSpeedSetting {"visionSqueezeUnSqueezeSpeed", + DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED}; + Setting::Handle _visionSqueezeTransitionSetting {"visionSqueezeTransition", DEFAULT_VISION_SQUEEZE_TRANSITION}; + Setting::Handle _visionSqueezePerEyeSetting {"visionSqueezePerEye", DEFAULT_VISION_SQUEEZE_PER_EYE}; + Setting::Handle _visionSqueezeGroundPlaneYSetting {"visionSqueezeGroundPlaneY", + DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y}; + Setting::Handle _visionSqueezeSpotlightSizeSetting {"visionSqueezeSpotlightSize", + DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE}; + Setting::Handle _visionSqueezeTurningXFactorSetting {"visionSqueezeTurningXFactor", + DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR}; + Setting::Handle _visionSqueezeTurningYFactorSetting {"visionSqueezeTurningYFactor", + DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR}; + + + // these are readable and writable from the scripting interface (on a different thread), so make them atomic + std::atomic _visionSqueezeEnabled { false }; + std::atomic _visionSqueezeRatioX { 0.0f }; + std::atomic _visionSqueezeRatioY { 0.0f }; + std::atomic _visionSqueezeUnSqueezeDelay { DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY }; // seconds + std::atomic _visionSqueezeUnSqueezeSpeed { DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED }; + std::atomic _visionSqueezeTransition { DEFAULT_VISION_SQUEEZE_TRANSITION }; + std::atomic _visionSqueezePerEye { DEFAULT_VISION_SQUEEZE_PER_EYE }; + std::atomic _visionSqueezeGroundPlaneY { DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y }; + std::atomic _visionSqueezeSpotlightSize { DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE }; + std::atomic _visionSqueezeTurningXFactor { DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR }; + std::atomic _visionSqueezeTurningYFactor { DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR }; + + bool _squeezeVision { false }; + bool _squeezeVisionTurning { false }; + + float _visionSqueezeLockout { 0.0 }; + glm::vec3 _prevTranslation; + glm::quat _prevRotation; +}; + +#endif // hifi_VisionSqueeze_h diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index cce2af466d..acb199bb97 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -6144,4 +6144,3 @@ void MyAvatar::sendPacket(const QUuid& entityID) const { }); } } - diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index baca6250d2..8f7ae7c4dc 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -236,3 +236,83 @@ QVariant HMDScriptingInterface::getPlayAreaRect() { QVector HMDScriptingInterface::getSensorPositions() { return qApp->getActiveDisplayPlugin()->getSensorPositions(); } + +float HMDScriptingInterface::getVisionSqueezeRatioX() const { + return qApp->getVisionSqueeze().getVisionSqueezeRatioX(); +} + +float HMDScriptingInterface::getVisionSqueezeRatioY() const { + return qApp->getVisionSqueeze().getVisionSqueezeRatioY(); +} + +void HMDScriptingInterface::setVisionSqueezeRatioX(float value) { + qApp->getVisionSqueeze().setVisionSqueezeRatioX(value); +} + +void HMDScriptingInterface::setVisionSqueezeRatioY(float value) { + qApp->getVisionSqueeze().setVisionSqueezeRatioY(value); +} + +float HMDScriptingInterface::getVisionSqueezeUnSqueezeDelay() const { + return qApp->getVisionSqueeze().getVisionSqueezeUnSqueezeDelay(); +} + +void HMDScriptingInterface::setVisionSqueezeUnSqueezeDelay(float value) { + qApp->getVisionSqueeze().setVisionSqueezeUnSqueezeDelay(value); +} + +float HMDScriptingInterface::getVisionSqueezeUnSqueezeSpeed() const { + return qApp->getVisionSqueeze().getVisionSqueezeUnSqueezeSpeed(); +} + +void HMDScriptingInterface::setVisionSqueezeUnSqueezeSpeed(float value) { + qApp->getVisionSqueeze().setVisionSqueezeUnSqueezeSpeed(value); +} + +float HMDScriptingInterface::getVisionSqueezeTransition() const { + return qApp->getVisionSqueeze().getVisionSqueezeTransition(); +} + +void HMDScriptingInterface::setVisionSqueezeTransition(float value) { + qApp->getVisionSqueeze().setVisionSqueezeTransition(value); +} + +int HMDScriptingInterface::getVisionSqueezePerEye() const { + return qApp->getVisionSqueeze().getVisionSqueezePerEye(); +} + +void HMDScriptingInterface::setVisionSqueezePerEye(int value) { + qApp->getVisionSqueeze().setVisionSqueezePerEye(value); +} + +float HMDScriptingInterface::getVisionSqueezeGroundPlaneY() const { + return qApp->getVisionSqueeze().getVisionSqueezeGroundPlaneY(); +} + +void HMDScriptingInterface::setVisionSqueezeGroundPlaneY(float value) { + qApp->getVisionSqueeze().setVisionSqueezeGroundPlaneY(value); +} + +float HMDScriptingInterface::getVisionSqueezeSpotlightSize() const { + return qApp->getVisionSqueeze().getVisionSqueezeSpotlightSize(); +} + +void HMDScriptingInterface::setVisionSqueezeSpotlightSize(float value) { + qApp->getVisionSqueeze().setVisionSqueezeSpotlightSize(value); +} + +float HMDScriptingInterface::getVisionSqueezeTurningXFactor() const { + return qApp->getVisionSqueeze().getVisionSqueezeTurningXFactor(); +} + +void HMDScriptingInterface::setVisionSqueezeTurningXFactor(float value) { + qApp->getVisionSqueeze().setVisionSqueezeTurningXFactor(value); +} + +float HMDScriptingInterface::getVisionSqueezeTurningYFactor() const { + return qApp->getVisionSqueeze().getVisionSqueezeTurningYFactor(); +} + +void HMDScriptingInterface::setVisionSqueezeTurningYFactor(float value) { + qApp->getVisionSqueeze().setVisionSqueezeTurningYFactor(value); +} diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 335816bf7c..ad3b4404a8 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -84,6 +84,17 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen Q_PROPERTY(QVariant playArea READ getPlayAreaRect); Q_PROPERTY(QVector sensorPositions READ getSensorPositions); + Q_PROPERTY(float visionSqueezeRatioX READ getVisionSqueezeRatioX WRITE setVisionSqueezeRatioX); + Q_PROPERTY(float visionSqueezeRatioY READ getVisionSqueezeRatioY WRITE setVisionSqueezeRatioY); + Q_PROPERTY(float visionSqueezeUnSqueezeDelay READ getVisionSqueezeUnSqueezeDelay WRITE setVisionSqueezeUnSqueezeDelay); + Q_PROPERTY(float visionSqueezeUnSqueezeSpeed READ getVisionSqueezeUnSqueezeSpeed WRITE setVisionSqueezeUnSqueezeSpeed); + Q_PROPERTY(float visionSqueezeTransition READ getVisionSqueezeTransition WRITE setVisionSqueezeTransition); + Q_PROPERTY(int visionSqueezePerEye READ getVisionSqueezePerEye WRITE setVisionSqueezePerEye); + Q_PROPERTY(float visionSqueezeGroundPlaneY READ getVisionSqueezeGroundPlaneY WRITE setVisionSqueezeGroundPlaneY); + Q_PROPERTY(float visionSqueezeSpotlightSize READ getVisionSqueezeSpotlightSize WRITE setVisionSqueezeSpotlightSize); + Q_PROPERTY(float visionSqueezeTurningXFactor READ getVisionSqueezeTurningXFactor WRITE setVisionSqueezeTurningXFactor); + Q_PROPERTY(float visionSqueezeTurningYFactor READ getVisionSqueezeTurningYFactor WRITE setVisionSqueezeTurningYFactor); + public: /**jsdoc @@ -339,6 +350,27 @@ public: */ Q_INVOKABLE void openTablet(bool contextualMode = false); + float getVisionSqueezeRatioX() const; + float getVisionSqueezeRatioY() const; + void setVisionSqueezeRatioX(float value); + void setVisionSqueezeRatioY(float value); + float getVisionSqueezeUnSqueezeDelay() const; + void setVisionSqueezeUnSqueezeDelay(float value); + float getVisionSqueezeUnSqueezeSpeed() const; + void setVisionSqueezeUnSqueezeSpeed(float value); + float getVisionSqueezeTransition() const; + void setVisionSqueezeTransition(float value); + int getVisionSqueezePerEye() const; + void setVisionSqueezePerEye(int value); + float getVisionSqueezeGroundPlaneY() const; + void setVisionSqueezeGroundPlaneY(float value); + float getVisionSqueezeSpotlightSize() const; + void setVisionSqueezeSpotlightSize(float value); + float getVisionSqueezeTurningXFactor() const; + void setVisionSqueezeTurningXFactor(float value); + float getVisionSqueezeTurningYFactor() const; + void setVisionSqueezeTurningYFactor(float value); + signals: /**jsdoc * Triggered when a request to show or hide models of the HMD hand controllers is made using diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index ce70e91128..ec15dd8111 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include "scripting/RenderScriptingInterface.h" #include "Application.h" #include "DialogsManager.h" @@ -377,6 +378,33 @@ void setupPreferences() { preference->setDecimals(2); preferences->addPreference(preference); } + { + auto getter = []()->bool { + return qApp->getVisionSqueeze().getVisionSqueezeEnabled(); + }; + auto setter = [](bool value) { + qApp->getVisionSqueeze().setVisionSqueezeEnabled(value); + }; + auto preference = new CheckPreference(VR_MOVEMENT, "Enable HMD Comfort Mode", getter, setter); + preferences->addPreference(preference); + } + { + const float sliderPositions = 5.0f; + auto getter = [sliderPositions]()->float { + return roundf(sliderPositions * qApp->getVisionSqueeze().getVisionSqueezeRatioX()); + }; + auto setter = [sliderPositions](float value) { + float ratio = value / sliderPositions; + qApp->getVisionSqueeze().setVisionSqueezeRatioX(ratio); + qApp->getVisionSqueeze().setVisionSqueezeRatioY(ratio); + }; + auto preference = new SpinnerSliderPreference(VR_MOVEMENT, "Comfort Mode", getter, setter); + preference->setMin(0.0f); + preference->setMax(sliderPositions); + preference->setStep(1.0f); + preference->setDecimals(0); + preferences->addPreference(preference); + } { auto getter = [myAvatar]()->bool { return myAvatar->getShowPlayArea(); }; auto setter = [myAvatar](bool value) { myAvatar->setShowPlayArea(value); }; diff --git a/libraries/display-plugins/src/display-plugins/DrawTextureWithVisionSqueeze.slf b/libraries/display-plugins/src/display-plugins/DrawTextureWithVisionSqueeze.slf new file mode 100644 index 0000000000..1092608421 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/DrawTextureWithVisionSqueeze.slf @@ -0,0 +1,104 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// DrawTextureWithVisionSqueeze.frag +// +// Draw texture 0 fetched at texcoord.xy +// +// Created by Seth Alves on 2019-2-15 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include display-plugins/VisionSqueeze.slh@> + +struct DrawTextureWithVisionSqueezeParams { + float _visionSqueezeX; + float _visionSqueezeY; + float _spareA; + float _spareB; + mat4 _leftProjection; + mat4 _rightProjection; + mat4 _hmdSensorMatrix; + float _visionSqueezeTransition; + int _visionSqueezePerEye; + float _visionSqueezeGroundPlaneY; + float _visionSqueezeSpotlightSize; +}; + + +LAYOUT(binding=0) uniform sampler2D colorMap; + +// binding=1 must match drawTextureWithSqueezeParamsSlot in OpenGLDisplayPlugin.h +LAYOUT(binding=1) uniform drawTextureWithSqueezeMappingParamsBuffer { + DrawTextureWithVisionSqueezeParams params; +}; + +layout(location=0) in vec2 varTexCoord0; +layout(location=0) out vec4 outFragColor; + + +float getVisionSqueezeX() { + return params._visionSqueezeX; +} +float getVisionSqueezeY() { + return params._visionSqueezeY; +} +float getVisionSqueezeTransitionRatio() { + return params._visionSqueezeTransition; +} +int getVisionSqueezePerEye() { + return params._visionSqueezePerEye; +} +float getVisionSqueezeGroundPlaneY() { + return params._visionSqueezeGroundPlaneY; +} +float getVisionSqueezeSpotlightSize() { + return params._visionSqueezeSpotlightSize; +} +mat4 getProjectionMatrix(float eye) { + if (eye == 0.0) { + return params._leftProjection; + } else { + return params._rightProjection; + } +} +mat4 getHMDSensorMatrix() { + return params._hmdSensorMatrix; +} + + +void main(void) { + + float side = float(varTexCoord0.x > 0.5); + mat4 leftProjectionMatrix = getProjectionMatrix(0.0); + vec4 fovTan = extractFovTan(leftProjectionMatrix); + vec2 focalPointNDC = extractFocalPoint(fovTan); + focalPointNDC.x -= 2.0 * focalPointNDC.x * (1.0 - side); + vec2 focalPointUV = 0.5 * (focalPointNDC + vec2(1.0)); + + // block edges of vision to avoid sickness + vec2 visionSqueezeRatios = vec2(getVisionSqueezeX(), getVisionSqueezeY()); + bool perEye = getVisionSqueezePerEye() > 0; + float frac = squeezeVision(perEye, varTexCoord0, visionSqueezeRatios, getVisionSqueezeTransitionRatio(), focalPointUV); + + if (frac == 0.0) { + // world only + outFragColor = texture(colorMap, varTexCoord0); + } else { + // grid on the floor only or mixed + mat4 hmdSensorMatrix = getHMDSensorMatrix(); + mat4 projectionMatrix = getProjectionMatrix(side); + mat4 projectionInverse = inverse(projectionMatrix); + float groundPlaneY = getVisionSqueezeGroundPlaneY(); + float spotLightSize = getVisionSqueezeSpotlightSize(); + vec4 gridColor = vec4(gridFloor(varTexCoord0, hmdSensorMatrix, projectionInverse, groundPlaneY, spotLightSize), 1.0); + + vec4 preSqueezeColor = texture(colorMap, varTexCoord0); + // mix between grid and world + outFragColor = mix(preSqueezeColor, gridColor, frac); + } +} diff --git a/libraries/display-plugins/src/display-plugins/DrawTextureWithVisionSqueeze.slp b/libraries/display-plugins/src/display-plugins/DrawTextureWithVisionSqueeze.slp new file mode 100644 index 0000000000..c2c4bfbebd --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/DrawTextureWithVisionSqueeze.slp @@ -0,0 +1 @@ +VERTEX gpu::vertex::DrawUnitQuadTexcoord diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index ebbf888e83..1d0fc5a128 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -392,6 +392,9 @@ void OpenGLDisplayPlugin::customizeContext() { _drawTexturePipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), scissorState); + _drawTextureSqueezePipeline = + gpu::Pipeline::create(gpu::Shader::createProgram(shader::display_plugins::program::DrawTextureWithVisionSqueeze), scissorState); + _linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureLinearToSRGB), scissorState); _SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureSRGBToLinear), scissorState); @@ -407,6 +410,7 @@ void OpenGLDisplayPlugin::customizeContext() { void OpenGLDisplayPlugin::uncustomizeContext() { _drawTexturePipeline.reset(); + _drawTextureSqueezePipeline.reset(); _linearToSRGBPipeline.reset(); _SRGBToLinearPipeline.reset(); _cursorPipeline.reset(); @@ -629,6 +633,10 @@ void OpenGLDisplayPlugin::compositePointer() { }); } +void OpenGLDisplayPlugin::setupCompositeScenePipeline(gpu::Batch& batch) { + batch.setPipeline(_drawTexturePipeline); +} + void OpenGLDisplayPlugin::compositeScene() { render([&](gpu::Batch& batch) { batch.enableStereo(false); @@ -637,8 +645,8 @@ void OpenGLDisplayPlugin::compositeScene() { batch.setStateScissorRect(ivec4(uvec2(), _compositeFramebuffer->getSize())); batch.resetViewTransform(); batch.setProjectionTransform(mat4()); - batch.setPipeline(_drawTexturePipeline); batch.setResourceTexture(0, _currentFrame->framebuffer->getRenderBuffer(0)); + setupCompositeScenePipeline(batch); batch.draw(gpu::TRIANGLE_STRIP, 4); }); } @@ -958,4 +966,3 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne gpu::PipelinePointer OpenGLDisplayPlugin::getRenderTexturePipeline() { return _drawTexturePipeline; } - diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 6fb36bff90..5eebd92fba 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -100,6 +100,7 @@ protected: virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; } virtual void compositeLayers(); + virtual void setupCompositeScenePipeline(gpu::Batch& batch); virtual void compositeScene(); virtual void compositePointer(); virtual void compositeExtra(){}; @@ -155,6 +156,7 @@ protected: gpu::PipelinePointer _mirrorHUDPipeline; gpu::ShaderPointer _mirrorHUDPS; gpu::PipelinePointer _drawTexturePipeline; + gpu::PipelinePointer _drawTextureSqueezePipeline; gpu::PipelinePointer _linearToSRGBPipeline; gpu::PipelinePointer _SRGBToLinearPipeline; gpu::PipelinePointer _cursorPipeline; diff --git a/libraries/display-plugins/src/display-plugins/VisionSqueeze.slh b/libraries/display-plugins/src/display-plugins/VisionSqueeze.slh new file mode 100644 index 0000000000..28e5f12337 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/VisionSqueeze.slh @@ -0,0 +1,106 @@ +// Generated on <$_SCRIBE_DATE$> +// +// Created by Seth Alves on 2019-2-13. +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@if not VISION_SQUEEZE_SLH@> +<@def VISION_SQUEEZE_SLH@> + + +float ellipse(vec2 coord, vec2 centerUV, vec2 semiAxis) { + return pow(coord.x - centerUV.x, 2.0) / semiAxis.x + pow(coord.y - centerUV.y, 2.0) / semiAxis.y; +} + +vec4 extractFovTan(mat4 m) { + mat4 mt = transpose(m); + vec4 v; + vec4 result; + + // x -- Left + v = mt * vec4(1.0, 0.0, 0.0, 1.0); + result.x = -(v.z / v.x); + // y -- Right + v = mt * vec4(-1.0, 0.0, 0.0, 1.0); + result.y = (v.z / v.x); + // z -- Down + v = mt * vec4(0.0, 1.0, 0.0, 1.0); + result.z = -(v.z / v.y); + // w -- Up + v = mt * vec4(0.0, -1.0, 0.0, 1.0); + result.w = v.z / v.y; + return result; +} + +// takes left-side projection matrix, returns NDC for right eye. to get left, invert sign on x coord of result. +vec2 extractFocalPoint(vec4 fovTan) { + float fovwidth = fovTan.x + fovTan.y; + float fovheight = fovTan.z + fovTan.w; + vec2 focalPoint = vec2(fovTan.y / fovwidth, (fovTan.z / fovheight) - 0.5f); + return focalPoint; +} + +float squeezeVision(bool perEye, vec2 varTexCoord0, vec2 visionSqueezeRatios, float transitionRatio, vec2 focalPointUV) { + if (visionSqueezeRatios.x == 0.0 && visionSqueezeRatios.y == 0.0) { + return 0.0; + } + + vec2 centerUV; + vec2 semiAxis; + if (perEye) { + // tubes in front of each eye + centerUV = focalPointUV; + semiAxis = vec2(0.25) - visionSqueezeRatios * 0.25; + } else { + // one tube in front of face + centerUV = vec2(0.5, focalPointUV.y); + semiAxis = vec2(0.5) - visionSqueezeRatios * 0.5; + } + float ellipseValue = ellipse(varTexCoord0, centerUV, semiAxis); + float frac = clamp((ellipseValue - 1.0) / clamp(transitionRatio, 0.01, 0.7), 0.0, 1.0); + + return frac; +} + +vec3 gridFloor(vec2 varTexCoord0, mat4 hmdSensorMatrix, mat4 projectionInverse, float groundPlaneY, float spotLightSize) { + vec4 ndc = vec4(varTexCoord0.x * 4.0 - 1.0 - 2.0 * float(varTexCoord0.x > 0.5), varTexCoord0.y * 2.0 - 1.0, -1.0, 1.0); + + vec4 fragmentEyeCoords = hmdSensorMatrix * projectionInverse * ndc; + vec4 near4 = hmdSensorMatrix * vec4(0.0, 0.0, 0.0, 1.0); + + vec3 near = (near4 / near4.w).xyz; + vec3 far = fragmentEyeCoords.xyz / fragmentEyeCoords.w; + + // intersect a line from near to far with the plane y = groundPlaneY + float t = -(near.y - groundPlaneY) / (far.y - near.y); + vec2 R = (near + t * (far - near)).xz; + + float lineThickness = 1.5 / length(R); + vec4 gridColor = vec4(0.35); + vec4 baseColor = vec4(0.1); + vec4 skyColor = vec4(0.0, 0.0, 0.0, 0.0); + vec2 wrapped = fract(R) - 0.5f; + vec2 range = abs(wrapped); + vec2 speeds = fwidth(R); + vec2 pixelRange = range/speeds; + float lineWeight = clamp(min(pixelRange.x, pixelRange.y) - lineThickness, 0.0, 1.0); + + float horizonFuzz = 0.02; + if (t < 0.0) { + return mix(gridColor, skyColor, clamp(0.0, 1.0, -t)).xyz; + } else if (t < horizonFuzz) { + lineWeight = lineWeight * max(0.0, t); + } + + vec4 c = mix(gridColor, baseColor, lineWeight); + + // fade out grid to avoid shimmer + float fadeVal = 0.7; + return mix(c, baseColor * fadeVal + gridColor * (1.0 - fadeVal), + 0.1 * clamp((length(R) - spotLightSize), 0.0, 1.0)).xyz; +} + +<@endif@> diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 3cec5e8265..9cbf189b38 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -1,4 +1,4 @@ -// +// // Created by Bradley Austin Davis on 2016/02/15 // Copyright 2016 High Fidelity, Inc. // @@ -113,6 +113,11 @@ void HmdDisplayPlugin::internalDeactivate() { } void HmdDisplayPlugin::customizeContext() { + + VisionSqueezeParameters parameters; + _visionSqueezeParametersBuffer = + gpu::BufferView(std::make_shared(sizeof(VisionSqueezeParameters), (const gpu::Byte*) ¶meters)); + Parent::customizeContext(); _hudRenderer.build(); } @@ -478,3 +483,57 @@ HmdDisplayPlugin::~HmdDisplayPlugin() { float HmdDisplayPlugin::stutterRate() const { return _stutterRate.rate(); } + +float adjustVisionSqueezeRatioForDevice(float visionSqueezeRatio, float visionSqueezeDeviceLow, float visionSqueezeDeviceHigh) { + const float SETTINGS_STEP = 0.2f; // adjusting the slider in preferences changes the ratio by this much + + if (visionSqueezeRatio == 0.0f) { + return 0.0f; + } + + float deviceRange = visionSqueezeDeviceHigh - visionSqueezeDeviceLow; + + if (visionSqueezeRatio <= SETTINGS_STEP) { + // lowest "enabled" setting -- without this special case the user doesn't see anything on the lowest setting + float scaleFactor = (visionSqueezeRatio == SETTINGS_STEP) ? 0.24f : 0.18f; // these magic values were picked through experimentation + return deviceRange * scaleFactor + visionSqueezeDeviceLow; + } else { + const float SQUEEZE_ADJUSTMENT = 0.75f; // magic number picked through experimentation + return deviceRange * (SQUEEZE_ADJUSTMENT * visionSqueezeRatio) + visionSqueezeDeviceLow; + } +} + +void HmdDisplayPlugin::updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY, + float visionSqueezeTransition, + int visionSqueezePerEye, float visionSqueezeGroundPlaneY, + float visionSqueezeSpotlightSize) { + + visionSqueezeX = adjustVisionSqueezeRatioForDevice(visionSqueezeX, _visionSqueezeDeviceLowX, _visionSqueezeDeviceHighX); + visionSqueezeY = adjustVisionSqueezeRatioForDevice(visionSqueezeY, _visionSqueezeDeviceLowY, _visionSqueezeDeviceHighY); + + auto& params = _visionSqueezeParametersBuffer.get(); + if (params._visionSqueezeX != visionSqueezeX) { + _visionSqueezeParametersBuffer.edit()._visionSqueezeX = visionSqueezeX; + } + if (params._visionSqueezeY != visionSqueezeY) { + _visionSqueezeParametersBuffer.edit()._visionSqueezeY = visionSqueezeY; + } + if (params._visionSqueezeTransition != visionSqueezeTransition) { + _visionSqueezeParametersBuffer.edit()._visionSqueezeTransition = visionSqueezeTransition; + } + if (params._visionSqueezePerEye != visionSqueezePerEye) { + _visionSqueezeParametersBuffer.edit()._visionSqueezePerEye = visionSqueezePerEye; + } + if (params._visionSqueezeGroundPlaneY != visionSqueezeGroundPlaneY) { + _visionSqueezeParametersBuffer.edit()._visionSqueezeGroundPlaneY = visionSqueezeGroundPlaneY; + } + if (params._visionSqueezeSpotlightSize != visionSqueezeSpotlightSize) { + _visionSqueezeParametersBuffer.edit()._visionSqueezeSpotlightSize = visionSqueezeSpotlightSize; + } +} + +void HmdDisplayPlugin::setupCompositeScenePipeline(gpu::Batch& batch) { + batch.setPipeline(_drawTextureSqueezePipeline); + _visionSqueezeParametersBuffer.edit()._hmdSensorMatrix = _currentPresentFrameInfo.presentPose; + batch.setUniformBuffer(drawTextureWithVisionSqueezeParamsSlot, _visionSqueezeParametersBuffer); +} diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index a381f04689..5317ec54da 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -50,6 +50,9 @@ public: std::function getHUDOperator() override; virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::PAINT; } + void updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition, + int visionSqueezePerEye, float visionSqueezeGroundPlaneY, + float visionSqueezeSpotlightSize); signals: void hmdMountedChanged(); @@ -91,6 +94,33 @@ protected: RateCounter<> _stutterRate; bool _disablePreview { true }; + + class VisionSqueezeParameters { + public: + float _visionSqueezeX { 0.0f }; + float _visionSqueezeY { 0.0f }; + float _spareA { 0.0f }; + float _spareB { 0.0f }; + glm::mat4 _leftProjection; + glm::mat4 _rightProjection; + glm::mat4 _hmdSensorMatrix; + float _visionSqueezeTransition { 0.15f }; + int _visionSqueezePerEye { 0 }; + float _visionSqueezeGroundPlaneY { 0.0f }; + float _visionSqueezeSpotlightSize { 0.0f }; + + VisionSqueezeParameters() {} + }; + typedef gpu::BufferView UniformBufferView; + gpu::BufferView _visionSqueezeParametersBuffer; + + virtual void setupCompositeScenePipeline(gpu::Batch& batch) override; + + float _visionSqueezeDeviceLowX { 0.0f }; + float _visionSqueezeDeviceHighX { 1.0f }; + float _visionSqueezeDeviceLowY { 0.0f }; + float _visionSqueezeDeviceHighY { 1.0f }; + private: ivec4 getViewportForSourceSize(const uvec2& size) const; float getLeftCenterPixel() const; @@ -112,7 +142,7 @@ private: struct Uniforms { float alpha { 1.0f }; } uniforms; - + struct Vertex { vec3 pos; vec2 uv; @@ -126,3 +156,5 @@ private: std::function render(); } _hudRenderer; }; + +const int drawTextureWithVisionSqueezeParamsSlot = 1; // must match binding in DrawTextureWithVisionSqueeze.slf diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 927e872fbc..97b67586c6 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -220,7 +220,7 @@ double Context::getFrameTimerBatchAverage() const { const Backend::TransformCamera& Backend::TransformCamera::recomputeDerived(const Transform& xformView) const { _projectionInverse = glm::inverse(_projection); - // Get the viewEyeToWorld matrix form the transformView as passed to the gpu::Batch + // Get the viewEyeToWorld matrix from the transformView as passed to the gpu::Batch // this is the "_viewInverse" fed to the shader // Genetrate the "_view" matrix as well from the xform xformView.getMatrix(_viewInverse); diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 2315f6e4ba..5c95bf05f8 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -214,6 +214,9 @@ public: virtual StencilMaskMode getStencilMaskMode() const { return StencilMaskMode::NONE; } using StencilMaskMeshOperator = std::function; virtual StencilMaskMeshOperator getStencilMaskMeshOperator() { return nullptr; } + virtual void updateParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition, + int visionSqueezePerEye, float visionSqueezeGroundPlaneY, + float visionSqueezeSpotlightSize) {} signals: void recommendedFramebufferSizeChanged(const QSize& size); diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index cb1ca668a7..a75192bad7 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -142,6 +142,13 @@ namespace render { bool _takingSnapshot { false }; StencilMaskMode _stencilMaskMode { StencilMaskMode::NONE }; std::function _stencilMaskOperator; + + float _visionSqueezeX { 0.0f }; + float _visionSqueezeY { 0.0f }; + float _visionSqueezeTransition { 0.15f }; + int _visionSqueezePerEye { 0 }; + float _visionSqueezeGroundPlaneY { 0.0f }; + float _visionSqueezeSpotlightSize { 0.02f }; }; } diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index bd0c77ae57..b2fc6881f4 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -53,6 +53,13 @@ bool OculusDisplayPlugin::internalActivate() { void OculusDisplayPlugin::init() { Plugin::init(); + // Different HMDs end up showing the squeezed-vision egg as different sizes. These values + // attempt to make them appear the same. + _visionSqueezeDeviceLowX = 0.8f; + _visionSqueezeDeviceHighX = 0.98f; + _visionSqueezeDeviceLowY = 0.8f; + _visionSqueezeDeviceHighY = 0.9f; + emit deviceConnected(getName()); } @@ -151,8 +158,11 @@ void OculusDisplayPlugin::hmdPresent() { GLuint curTexId; ovr_GetTextureSwapChainBufferGL(_session, _textureSwapChain, curIndex, &curTexId); + _visionSqueezeParametersBuffer.edit()._leftProjection = _eyeProjections[0]; + _visionSqueezeParametersBuffer.edit()._rightProjection = _eyeProjections[1]; + // Manually bind the texture to the FBO - // FIXME we should have a way of wrapping raw GL ids in GPU objects without + // FIXME we should have a way of wrapping raw GL ids in GPU objects without // taking ownership of the object auto fbo = getGLBackend()->getFramebufferID(_outputFramebuffer); glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, curTexId, 0); diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index cd318dd9b4..78b462369b 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -396,6 +396,13 @@ void OpenVrDisplayPlugin::init() { _lastGoodHMDPose.m[2][2] = 1.0f; _lastGoodHMDPose.m[2][3] = 0.0f; + // Different HMDs end up showing the squeezed-vision egg as different sizes. These values + // attempt to make them appear the same. + _visionSqueezeDeviceLowX = 0.8f; + _visionSqueezeDeviceHighX = 0.98f; + _visionSqueezeDeviceLowY = 0.8f; + _visionSqueezeDeviceHighY = 0.9f; + emit deviceConnected(getName()); } @@ -651,6 +658,11 @@ void OpenVrDisplayPlugin::hmdPresent() { if (_threadedSubmit) { _submitThread->waitForPresent(); } else { + + _visionSqueezeParametersBuffer.edit()._leftProjection = _eyeProjections[0]; + _visionSqueezeParametersBuffer.edit()._rightProjection = _eyeProjections[1]; + _visionSqueezeParametersBuffer.edit()._hmdSensorMatrix = _currentPresentFrameInfo.presentPose; + GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0)); vr::Texture_t vrTexture{ (void*)(uintptr_t)glTexId, vr::TextureType_OpenGL, vr::ColorSpace_Auto }; vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT); @@ -828,4 +840,15 @@ DisplayPlugin::StencilMaskMeshOperator OpenVrDisplayPlugin::getStencilMaskMeshOp } } return nullptr; -} \ No newline at end of file +} + +void OpenVrDisplayPlugin::updateParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition, + int visionSqueezePerEye, float visionSqueezeGroundPlaneY, + float visionSqueezeSpotlightSize) { + _visionSqueezeX = visionSqueezeX; + _visionSqueezeY = visionSqueezeY; + _visionSqueezeTransition = visionSqueezeTransition; + _visionSqueezePerEye = visionSqueezePerEye; + _visionSqueezeGroundPlaneY = visionSqueezeGroundPlaneY; + _visionSqueezeSpotlightSize = visionSqueezeSpotlightSize; +} diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index 4b042a700d..25427c6dcd 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -72,6 +72,10 @@ public: virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::MESH; } virtual StencilMaskMeshOperator getStencilMaskMeshOperator() override; + virtual void updateParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition, + int visionSqueezePerEye, float visionSqueezeGroundPlaneY, + float visionSqueezeSpotlightSize) override; + protected: bool internalActivate() override; void internalDeactivate() override; @@ -102,4 +106,11 @@ private: std::array _stencilMeshes; bool _stencilMeshesInitialized { false }; + + float _visionSqueezeX; + float _visionSqueezeY; + float _visionSqueezeTransition; + int _visionSqueezePerEye; + float _visionSqueezeGroundPlaneY; + float _visionSqueezeSpotlightSize; }; From 7ce6dd71d55174ea4faf76cdf8a9c99cbe7a78cb Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 12 Jul 2019 10:48:05 -0700 Subject: [PATCH 47/77] fix comment --- interface/src/MacHelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/MacHelper.cpp b/interface/src/MacHelper.cpp index b3513afdc9..8527f02918 100755 --- a/interface/src/MacHelper.cpp +++ b/interface/src/MacHelper.cpp @@ -17,7 +17,7 @@ #include #include -// These type definitions come from IOKit, which includes a definition of Duration that conflicts with ours. +// The type definitions in these variables come from IOKit, which includes a definition of Duration that conflicts with ours. // So... we include these definitions here rather than in the .h, as the .h is included in Application.cpp which // uses Duration. static io_connect_t root_port; From f78c1cb5d08cd4719e62c596ad5b6b138f4d2656 Mon Sep 17 00:00:00 2001 From: amerhifi Date: Fri, 12 Jul 2019 10:54:08 -0700 Subject: [PATCH 48/77] reverting display plugin reset change --- interface/src/Application.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index abcafd5a3e..e09819c11c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2772,6 +2772,7 @@ void Application::cleanupBeforeQuit() { DependencyManager::get()->removeAccountFromFile(); } + _displayPlugin.reset(); PluginManager::getInstance()->shutdown(); // Cleanup all overlays after the scripts, as scripts might add more @@ -2806,11 +2807,8 @@ void Application::cleanupBeforeQuit() { DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - DependencyManager::destroy(); - _displayPlugin.reset(); - _snapshotSoundInjector = nullptr; // destroy Audio so it and its threads have a chance to go down safely From ba6307e8e4330b30ae62114e26a87bc9a2be782b Mon Sep 17 00:00:00 2001 From: amerhifi Date: Fri, 12 Jul 2019 10:55:44 -0700 Subject: [PATCH 49/77] revert of extra space --- interface/src/Application.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e09819c11c..8ec1577915 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2807,6 +2807,7 @@ void Application::cleanupBeforeQuit() { DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); + DependencyManager::destroy(); _snapshotSoundInjector = nullptr; From e0392642f71110f515b92c454ee0add656854282 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 12 Jul 2019 11:18:34 -0700 Subject: [PATCH 50/77] Don't enable supersampling from graphics settings --- .../resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml index 88709c8be7..65e74768c1 100644 --- a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml +++ b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml @@ -346,7 +346,7 @@ Item { height: parent.height colorScheme: hifi.colorSchemes.dark minimumValue: 0.25 - maximumValue: 1.5 + maximumValue: 1.0 stepSize: 0.02 value: Render.viewportResolutionScale live: true From 5828f46c6b3928081608c94ddeedc4a802ce542a Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 12 Jul 2019 12:27:55 -0700 Subject: [PATCH 51/77] Incorrect ID fixed - thanks Milad --- .../resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml index 65e74768c1..f7c82c90a1 100644 --- a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml +++ b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml @@ -34,7 +34,6 @@ Item { spacing: 8 ColumnLayout { - id: avatarNameTagsContainer Layout.preferredWidth: parent.width Layout.topMargin: 18 spacing: 0 From aaf10cec395afc628deafec4421cf79da9d69387 Mon Sep 17 00:00:00 2001 From: PrestonB1123 Date: Fri, 12 Jul 2019 12:37:40 -0700 Subject: [PATCH 52/77] added conditionals to shortcuts to remove overlap --- scripts/system/keyboardShortcuts/keyboardShortcuts.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/keyboardShortcuts/keyboardShortcuts.js b/scripts/system/keyboardShortcuts/keyboardShortcuts.js index 165928d089..28a77aee89 100644 --- a/scripts/system/keyboardShortcuts/keyboardShortcuts.js +++ b/scripts/system/keyboardShortcuts/keyboardShortcuts.js @@ -14,11 +14,11 @@ (function () { // BEGIN LOCAL_SCOPE var snapActivateSound = SoundCache.getSound(Script.resourcesPath() + "sounds/snapshot/snap.wav"); function keyPressEvent(event) { - if (event.text.toUpperCase() === "B" && event.isControl) { + if (event.text.toUpperCase() === "B" && event.isControl && !event.isShifted && !event.isAlt) { Window.openWebBrowser(); - } else if (event.text.toUpperCase() === "N" && event.isControl) { + } else if (event.text.toUpperCase() === "N" && event.isControl && !event.isShifted && !event.isAlt) { Users.toggleIgnoreRadius(); - } else if (event.text.toUpperCase() === "P") { + } else if (event.text.toUpperCase() === "P" && !event.isControl && !event.isShifted && !event.isAlt) { Audio.playSound(snapActivateSound, { position: { x: MyAvatar.position.x, y: MyAvatar.position.y, z: MyAvatar.position.z }, localOnly: true, From 526b210fcd4b99cdd94d4b33b1473b37325de7b0 Mon Sep 17 00:00:00 2001 From: PrestonB1123 Date: Fri, 12 Jul 2019 12:39:58 -0700 Subject: [PATCH 53/77] remembered that macs exist --- scripts/system/keyboardShortcuts/keyboardShortcuts.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/keyboardShortcuts/keyboardShortcuts.js b/scripts/system/keyboardShortcuts/keyboardShortcuts.js index 28a77aee89..ca1429ad95 100644 --- a/scripts/system/keyboardShortcuts/keyboardShortcuts.js +++ b/scripts/system/keyboardShortcuts/keyboardShortcuts.js @@ -14,11 +14,11 @@ (function () { // BEGIN LOCAL_SCOPE var snapActivateSound = SoundCache.getSound(Script.resourcesPath() + "sounds/snapshot/snap.wav"); function keyPressEvent(event) { - if (event.text.toUpperCase() === "B" && event.isControl && !event.isShifted && !event.isAlt) { + if (event.text.toUpperCase() === "B" && event.isControl && !event.isShifted && !event.isAlt && !event.isCommand) { Window.openWebBrowser(); - } else if (event.text.toUpperCase() === "N" && event.isControl && !event.isShifted && !event.isAlt) { + } else if (event.text.toUpperCase() === "N" && event.isControl && !event.isShifted && !event.isAlt && !event.isCommand) { Users.toggleIgnoreRadius(); - } else if (event.text.toUpperCase() === "P" && !event.isControl && !event.isShifted && !event.isAlt) { + } else if (event.text.toUpperCase() === "P" && !event.isControl && !event.isShifted && !event.isAlt && !event.isCommand) { Audio.playSound(snapActivateSound, { position: { x: MyAvatar.position.x, y: MyAvatar.position.y, z: MyAvatar.position.z }, localOnly: true, From d78661a47f6c191a88a4e133b49a3e2dbb9b31bf Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Fri, 12 Jul 2019 13:34:08 -0700 Subject: [PATCH 54/77] redo requested work --- interface/src/ui/InteractiveWindow.cpp | 118 ++++++++----------------- interface/src/ui/InteractiveWindow.h | 15 ---- 2 files changed, 35 insertions(+), 98 deletions(-) diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index 2c580deb47..dff1f4dcb5 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -55,78 +55,6 @@ QmlWindowProxy::QmlWindowProxy(QObject* qmlObject, QObject* parent) : QmlWrapper _qmlWindow = qmlObject; } -void QmlWindowProxy::setPosition(const glm::vec2& position) { - if (_qmlWindow) { - _qmlWindow->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y)); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode"); - } -} - -glm::vec2 QmlWindowProxy::getPosition() const { - if (!_qmlWindow) { - return {}; - } - - return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF()); -} - -void QmlWindowProxy::setSize(const glm::vec2& size) { - if (_qmlWindow) { - _qmlWindow->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y)); - QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode"); - } -} - -glm::vec2 QmlWindowProxy::getSize() const { - if (!_qmlWindow) { - return {}; - } - - return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize()); -} - -void QmlWindowProxy::setTitle(const QString& title) { - if (_qmlWindow) { - _qmlWindow->setProperty(TITLE_PROPERTY, title); - } -} - -QString QmlWindowProxy::getTitle() const { - if (!_qmlWindow) { - return QString(); - } - - return _qmlWindow->property(TITLE_PROPERTY).toString(); -} - -void QmlWindowProxy::setVisible(bool visible) { - if (_qmlWindow) { - _qmlWindow->setProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY, visible); - } -} - -bool QmlWindowProxy::isVisible() const { - if (!_qmlWindow) { - return false; - } - - return _qmlWindow->property(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool(); -} - -void QmlWindowProxy::setPresentationMode(int presentationMode) { - if (_qmlWindow) { - _qmlWindow->setProperty(PRESENTATION_MODE_PROPERTY, presentationMode); - } -} - -int QmlWindowProxy::getPresentationMode() const { - if (!_qmlWindow) { - return Virtual; - } - - return _qmlWindow->property(PRESENTATION_MODE_PROPERTY).toInt(); -} - void QmlWindowProxy::parentNativeWindowToMainWindow() { #ifdef Q_OS_WIN if (!_qmlWindow) { @@ -395,7 +323,8 @@ void InteractiveWindow::qmlToScript(const QVariant& message) { void InteractiveWindow::setVisible(bool visible) { if (_qmlWindowProxy) { - QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setVisible", Q_ARG(bool, visible)); + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_VISIBLE_PROPERTY), + Q_ARG(QVariant, visible)); } } @@ -403,8 +332,10 @@ bool InteractiveWindow::isVisible() const { if (!_qmlWindowProxy) { return false; } - - return _qmlWindowProxy->isVisible(); + QVariant result; + BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), + Q_ARG(QString, INTERACTIVE_WINDOW_VISIBLE_PROPERTY)); + return result.toBool(); } glm::vec2 InteractiveWindow::getPosition() const { @@ -412,12 +343,18 @@ glm::vec2 InteractiveWindow::getPosition() const { return {}; } - return _qmlWindowProxy->getPosition(); + QVariant result; + BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), + Q_ARG(QString, INTERACTIVE_WINDOW_POSITION_PROPERTY)); + + return toGlm(result.toPointF()); } void InteractiveWindow::setPosition(const glm::vec2& position) { if (_qmlWindowProxy) { - QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setPosition", Q_ARG(const glm::vec2&, position)); + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_POSITION_PROPERTY), + Q_ARG(QVariant, QPointF(position.x, position.y))); + QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "updateInteractiveWindowPositionForMode"); } } @@ -425,12 +362,18 @@ glm::vec2 InteractiveWindow::getSize() const { if (!_qmlWindowProxy) { return {}; } - return _qmlWindowProxy->getSize(); + + QVariant result; + BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), + Q_ARG(QString, INTERACTIVE_WINDOW_SIZE_PROPERTY)); + return toGlm(result.toSize()); } void InteractiveWindow::setSize(const glm::vec2& size) { if (_qmlWindowProxy) { - QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setSize", Q_ARG(const glm::vec2&, size)); + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_SIZE_PROPERTY), + Q_ARG(QVariant, QSize(size.x, size.y))); + QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "updateInteractiveWindowSizeForMode"); } } @@ -438,12 +381,17 @@ QString InteractiveWindow::getTitle() const { if (!_qmlWindowProxy) { return QString(); } - return _qmlWindowProxy->getTitle(); + + QVariant result; + BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), + Q_ARG(QString, TITLE_PROPERTY)); + return result.toString(); } void InteractiveWindow::setTitle(const QString& title) { if (_qmlWindowProxy) { - QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setTitle", Q_ARG(const QString&, title)); + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, TITLE_PROPERTY), + Q_ARG(QVariant, title)); } } @@ -451,7 +399,10 @@ int InteractiveWindow::getPresentationMode() const { if (!_qmlWindowProxy) { return Virtual; } - return _qmlWindowProxy->getPresentationMode(); + QVariant result; + BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), + Q_ARG(QString, PRESENTATION_MODE_PROPERTY)); + return result.toInt(); } void InteractiveWindow::parentNativeWindowToMainWindow() { @@ -462,6 +413,7 @@ void InteractiveWindow::parentNativeWindowToMainWindow() { void InteractiveWindow::setPresentationMode(int presentationMode) { if (_qmlWindowProxy) { - QMetaObject::invokeMethod(_qmlWindowProxy.get(), "setPresentationMode", Q_ARG(int, presentationMode)); + QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, PRESENTATION_MODE_PROPERTY), + Q_ARG(QVariant, presentationMode)); } } diff --git a/interface/src/ui/InteractiveWindow.h b/interface/src/ui/InteractiveWindow.h index 7abdc5210a..0098658c16 100644 --- a/interface/src/ui/InteractiveWindow.h +++ b/interface/src/ui/InteractiveWindow.h @@ -29,21 +29,6 @@ class QmlWindowProxy : public QmlWrapper { public: QmlWindowProxy(QObject* qmlObject, QObject* parent = nullptr); - Q_INVOKABLE void setPosition(const glm::vec2& position); - glm::vec2 getPosition() const; - - Q_INVOKABLE void setSize(const glm::vec2& size); - glm::vec2 getSize() const; - - Q_INVOKABLE void setTitle(const QString& title); - QString getTitle() const; - - Q_INVOKABLE void setVisible(bool visible); - bool isVisible() const; - - Q_INVOKABLE void setPresentationMode(int presentationMode); - int getPresentationMode() const; - Q_INVOKABLE void parentNativeWindowToMainWindow(); QObject* getQmlWindow() const { return _qmlWindow; } From 54a2619b70781abf355092f1c895ae24dca1a1ee Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 12 Jul 2019 14:03:09 -0700 Subject: [PATCH 55/77] Move ci scripts to hifi repo --- .../linux-package-release/after-install.sh | 5 +++ .../assignment-client-before-install.sh | 17 +++++++++ .../linux-package-release/before-remove.sh | 6 ++++ .../domain-server-before-install.sh | 17 +++++++++ .../hifi-assignment-client | 12 +++++++ .../linux-package-release/hifi-domain-server | 13 +++++++ .../linux-package-release/hifi-ice-server | 14 ++++++++ .../ice-server-before-install.sh | 17 +++++++++ .../package-and-upload.sh | 35 +++++++++++++++++++ 9 files changed, 136 insertions(+) create mode 100755 tools/ci-scripts/linux-package-release/after-install.sh create mode 100755 tools/ci-scripts/linux-package-release/assignment-client-before-install.sh create mode 100755 tools/ci-scripts/linux-package-release/before-remove.sh create mode 100755 tools/ci-scripts/linux-package-release/domain-server-before-install.sh create mode 100644 tools/ci-scripts/linux-package-release/hifi-assignment-client create mode 100644 tools/ci-scripts/linux-package-release/hifi-domain-server create mode 100644 tools/ci-scripts/linux-package-release/hifi-ice-server create mode 100755 tools/ci-scripts/linux-package-release/ice-server-before-install.sh create mode 100755 tools/ci-scripts/linux-package-release/package-and-upload.sh diff --git a/tools/ci-scripts/linux-package-release/after-install.sh b/tools/ci-scripts/linux-package-release/after-install.sh new file mode 100755 index 0000000000..b3c99a27a8 --- /dev/null +++ b/tools/ci-scripts/linux-package-release/after-install.sh @@ -0,0 +1,5 @@ +#!/bin/bash +if ! systemctl is-active <%= service %> +then + systemctl start <%= service %> +fi diff --git a/tools/ci-scripts/linux-package-release/assignment-client-before-install.sh b/tools/ci-scripts/linux-package-release/assignment-client-before-install.sh new file mode 100755 index 0000000000..36883bfa9f --- /dev/null +++ b/tools/ci-scripts/linux-package-release/assignment-client-before-install.sh @@ -0,0 +1,17 @@ +#!/bin/bash +dpkg -s <%= service %> &>/dev/null +if [ $? -ne 0 ] +then + if systemctl is-active <%= service %> + then + # Stop service that is running + systemctl stop <%= service %> + fi +fi + +[ $(getent group hifi) ] || groupadd hifi +id -u hifi &>/dev/null || useradd hifi -g hifi --system --no-create-home +mkdir -p /.local && chown root:hifi /.local && chmod 775 /.local +mkdir -p /.config && chown root:hifi /.config && chmod 775 /.config +mkdir -p /var/log/hifi && chown root:hifi /var/log/hifi && chmod 775 /var/log/hifi +mkdir -p /usr/share/hifi/assignment-client && chown root:hifi /usr/share/hifi/assignment-client && chmod 775 /usr/share/hifi/assignment-client diff --git a/tools/ci-scripts/linux-package-release/before-remove.sh b/tools/ci-scripts/linux-package-release/before-remove.sh new file mode 100755 index 0000000000..d171cca810 --- /dev/null +++ b/tools/ci-scripts/linux-package-release/before-remove.sh @@ -0,0 +1,6 @@ +#!/bin/bash +if systemctl is-active <%= service %> +then + # Stop service that is running + systemctl stop <%= service %> +fi diff --git a/tools/ci-scripts/linux-package-release/domain-server-before-install.sh b/tools/ci-scripts/linux-package-release/domain-server-before-install.sh new file mode 100755 index 0000000000..390ac67382 --- /dev/null +++ b/tools/ci-scripts/linux-package-release/domain-server-before-install.sh @@ -0,0 +1,17 @@ +#!/bin/bash +dpkg -s <%= service %> &>/dev/null +if [ $? -ne 0 ] +then + if systemctl is-active <%= service %> + then + # Stop service that is running + systemctl stop <%= service %> + fi +fi + +[ $(getent group hifi) ] || groupadd hifi +id -u hifi &>/dev/null || useradd hifi -g hifi --system --no-create-home +mkdir -p /.local && chown root:hifi /.local && chmod 775 /.local +mkdir -p /.config && chown root:hifi /.config && chmod 775 /.config +mkdir -p /var/log/hifi && chown root:hifi /var/log/hifi && chmod 775 /var/log/hifi +mkdir -p /usr/share/hifi/domain-server && chown root:hifi /usr/share/hifi/domain-server && chmod 775 /usr/share/hifi/domain-server diff --git a/tools/ci-scripts/linux-package-release/hifi-assignment-client b/tools/ci-scripts/linux-package-release/hifi-assignment-client new file mode 100644 index 0000000000..ffd30882a1 --- /dev/null +++ b/tools/ci-scripts/linux-package-release/hifi-assignment-client @@ -0,0 +1,12 @@ +[Unit] +Description=Assignment client service for High Fidelity server +After=network.target +[Service] +Restart=always + +WorkingDirectory=/usr/share/hifi/assignment-client +Environment="LD_LIBRARY_PATH=/usr/share/hifi/assignment-client/" + +ExecStart=/bin/bash -c 'ulimit -c unlimited; /usr/share/hifi/assignment-client/assignment-client -n 7 2>&1 >> /var/log/hifi/assignment-client.log' +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/tools/ci-scripts/linux-package-release/hifi-domain-server b/tools/ci-scripts/linux-package-release/hifi-domain-server new file mode 100644 index 0000000000..aed34314dd --- /dev/null +++ b/tools/ci-scripts/linux-package-release/hifi-domain-server @@ -0,0 +1,13 @@ +[Unit] +Description=Domain Server service for High Fidelity +After=network.target +[Service] +Restart=on-failure + +WorkingDirectory=/usr/share/hifi/domain-server +Environment="LD_LIBRARY_PATH=/usr/share/hifi/domain-server/" + +ExecStartPre=/bin/bash -c 'if /usr/bin/pgrep -l domain-server; then /usr/bin/pkill -SIGKILL -f /usr/share/hifi/domain-server/domain-server; fi' +ExecStart=/bin/bash -c 'ulimit -c unlimited; /usr/share/hifi/domain-server/domain-server 2>&1 >> /var/log/hifi/domain-server.log' +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/tools/ci-scripts/linux-package-release/hifi-ice-server b/tools/ci-scripts/linux-package-release/hifi-ice-server new file mode 100644 index 0000000000..55b5e6d7de --- /dev/null +++ b/tools/ci-scripts/linux-package-release/hifi-ice-server @@ -0,0 +1,14 @@ +[Unit] +Description=Ice Server service for High Fidelity +After=network.target +[Service] +Restart=on-failure + +Environment="HIFI_ENVIRONMENT=production" + +WorkingDirectory=/usr/share/hifi/ice-server + +ExecStartPre=/bin/bash -c 'if /usr/bin/pgrep -l ice-server; then /usr/bin/pkill -SIGKILL -f /usr/share/hifi/ice-server/ice-server; fi' +ExecStart=/bin/bash -c 'ulimit -c unlimited; /usr/share/hifi/ice-server/ice-server 2>&1 >> /var/log/hifi/ice-server.log' +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/tools/ci-scripts/linux-package-release/ice-server-before-install.sh b/tools/ci-scripts/linux-package-release/ice-server-before-install.sh new file mode 100755 index 0000000000..1d415d61b7 --- /dev/null +++ b/tools/ci-scripts/linux-package-release/ice-server-before-install.sh @@ -0,0 +1,17 @@ +#!/bin/bash +dpkg -s <%= service %> &>/dev/null +if [ $? -ne 0 ] +then + if systemctl is-active <%= service %> + then + # Stop service that is running + systemctl stop <%= service %> + fi +fi + +[ $(getent group hifi) ] || groupadd hifi +id -u hifi &>/dev/null || useradd hifi -g hifi --system --no-create-home +mkdir -p /.local && chown root:hifi /.local && chmod 775 /.local +mkdir -p /.config && chown root:hifi /.config && chmod 775 /.config +mkdir -p /var/log/hifi && chown root:hifi /var/log/hifi && chmod 775 /var/log/hifi +mkdir -p /usr/share/hifi/ice-server && chown root:hifi /usr/share/hifi/ice-server && chmod 775 /usr/share/hifi/ice-server diff --git a/tools/ci-scripts/linux-package-release/package-and-upload.sh b/tools/ci-scripts/linux-package-release/package-and-upload.sh new file mode 100755 index 0000000000..c81b9eb72b --- /dev/null +++ b/tools/ci-scripts/linux-package-release/package-and-upload.sh @@ -0,0 +1,35 @@ +#!/bin/bash -l +prefix=${1:-""} +declare -a packages_systemd=("assignment-client" "domain-server" "ice-server") +cd ./build + +for package_name in "${packages_systemd[@]}" +do + SOURCE_DESTINATION_LIST="${WORKSPACE}/build/${package_name}/${package_name}=/usr/share/hifi/${package_name}/ " + if [ "$package_name" == "domain-server" ]; then + DESCRIPTION="High Fidelity Domain server." + SOURCE_DESTINATION_LIST+="${WORKSPACE}/build/${package_name}/resources/=/usr/share/hifi/${package_name}/resources " + SOURCE_DESTINATION_LIST+="${WORKSPACE}/build/ext/makefiles/quazip/project/build/libquazip5.so.1.0.0=/usr/share/hifi/${package_name}/libquazip5.so.1" + elif [ "$package_name" == "assignment-client" ]; then + DESCRIPTION="High Fidelity Assignment clients. Services target a local domain server. Different assignment clients are managed independently with systemd." + SOURCE_DESTINATION_LIST+="${WORKSPACE}/build/${package_name}/plugins/=/usr/share/hifi/${package_name}/plugins " + SOURCE_DESTINATION_LIST+="${WORKSPACE}/build/ext/makefiles/quazip/project/build/libquazip5.so.1.0.0=/usr/share/hifi/${package_name}/libquazip5.so.1 " + SOURCE_DESTINATION_LIST+="${WORKSPACE}/build/${package_name}/oven=/usr/share/hifi/${package_name}/oven" + elif [ "$package_name" == "ice-server" ]; then + DESCRIPTION="High Fidelity ICE server." + fi + + fpm -s dir -t deb -n hifi-${prefix}${package_name} -v ${VERSION} -d hifiqt5.12.3 --vendor "High Fidelity Inc" -m "" \ + --url "https://highfidelity.com" --license "Apache License 2.0" --description "${DESCRIPTION}" -d libgomp1 -d libtbb2 -d libgl1-mesa-glx -d libnss3 \ + -d libxi6 -d libxcursor1 -d libxcomposite1 -d libasound2 -d libxtst6 -d libxslt1.1 --template-scripts --template-value "service"="hifi-${package_name}" \ + --deb-systemd ${WORKSPACE}/hifi-${package_name} --before-install ${WORKSPACE}/${package_name}-before-install.sh \ + --after-install ${WORKSPACE}/after-install.sh --before-remove ${WORKSPACE}/before-remove.sh \ + ${SOURCE_DESTINATION_LIST} + + dpkg-sig --sign builder -k 15FF1AAE -g '--no-tty --passphrase "${MASKED_DEB_REPO_SIGN_PASSPHRASE}"' ./hifi-${prefix}${package_name}_${VERSION}_amd64.deb + + deb-s3 upload ./hifi-${prefix}${package_name}_${VERSION}_amd64.deb --bucket debian.highfidelity.com \ + --sign=15FF1AAE --gpg-options='--no-tty --passphrase "${MASKED_DEB_REPO_SIGN_PASSPHRASE}"' \ + --origin hifi --suite stable -p + +done From b93ec08f5a3f347557aef4de9f23ababc0206bed Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 12 Jul 2019 14:05:02 -0700 Subject: [PATCH 56/77] Modify path to resources --- tools/ci-scripts/linux-package-release/package-and-upload.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/ci-scripts/linux-package-release/package-and-upload.sh b/tools/ci-scripts/linux-package-release/package-and-upload.sh index c81b9eb72b..4bb377e58f 100755 --- a/tools/ci-scripts/linux-package-release/package-and-upload.sh +++ b/tools/ci-scripts/linux-package-release/package-and-upload.sh @@ -1,4 +1,5 @@ #!/bin/bash -l +LOCAL_PATH="`dirname \"$0\"`" prefix=${1:-""} declare -a packages_systemd=("assignment-client" "domain-server" "ice-server") cd ./build @@ -22,8 +23,8 @@ do fpm -s dir -t deb -n hifi-${prefix}${package_name} -v ${VERSION} -d hifiqt5.12.3 --vendor "High Fidelity Inc" -m "" \ --url "https://highfidelity.com" --license "Apache License 2.0" --description "${DESCRIPTION}" -d libgomp1 -d libtbb2 -d libgl1-mesa-glx -d libnss3 \ -d libxi6 -d libxcursor1 -d libxcomposite1 -d libasound2 -d libxtst6 -d libxslt1.1 --template-scripts --template-value "service"="hifi-${package_name}" \ - --deb-systemd ${WORKSPACE}/hifi-${package_name} --before-install ${WORKSPACE}/${package_name}-before-install.sh \ - --after-install ${WORKSPACE}/after-install.sh --before-remove ${WORKSPACE}/before-remove.sh \ + --deb-systemd ${LOCAL_PATH}/hifi-${package_name} --before-install ${LOCAL_PATH}/${package_name}-before-install.sh \ + --after-install ${LOCAL_PATH}/after-install.sh --before-remove ${LOCAL_PATH}/before-remove.sh \ ${SOURCE_DESTINATION_LIST} dpkg-sig --sign builder -k 15FF1AAE -g '--no-tty --passphrase "${MASKED_DEB_REPO_SIGN_PASSPHRASE}"' ./hifi-${prefix}${package_name}_${VERSION}_amd64.deb From 6ddccafa6b1949542fe1859c2d9c62e5bf280e77 Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 12 Jul 2019 15:29:05 -0700 Subject: [PATCH 57/77] Use absolute path --- tools/ci-scripts/linux-package-release/package-and-upload.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci-scripts/linux-package-release/package-and-upload.sh b/tools/ci-scripts/linux-package-release/package-and-upload.sh index 4bb377e58f..b38434dcc9 100755 --- a/tools/ci-scripts/linux-package-release/package-and-upload.sh +++ b/tools/ci-scripts/linux-package-release/package-and-upload.sh @@ -1,5 +1,5 @@ #!/bin/bash -l -LOCAL_PATH="`dirname \"$0\"`" +LOCAL_PATH="$( cd "$(dirname "$0")" ; pwd -P )" prefix=${1:-""} declare -a packages_systemd=("assignment-client" "domain-server" "ice-server") cd ./build From 1789e16cc48d4cc8492f23acd84a8b5238456a8b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 12 Jul 2019 16:22:01 -0700 Subject: [PATCH 58/77] possible fix for shader compilation error --- libraries/render-utils/src/ssao_gather.slf | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/render-utils/src/ssao_gather.slf b/libraries/render-utils/src/ssao_gather.slf index 1595678295..3e3b8e9120 100644 --- a/libraries/render-utils/src/ssao_gather.slf +++ b/libraries/render-utils/src/ssao_gather.slf @@ -20,8 +20,6 @@ // the source occlusion texture LAYOUT(binding=RENDER_UTILS_TEXTURE_SSAO_OCCLUSION) uniform sampler2DArray occlusionMaps; -layout(location=0) in vec4 varTexCoord0; - layout(location=0) out vec4 outFragColor; void main(void) { From 413a089402d99e58b436ea145a8ebe1dc0c590e6 Mon Sep 17 00:00:00 2001 From: dooglifeSF <41022919+dooglifeSF@users.noreply.github.com> Date: Mon, 15 Jul 2019 13:24:21 -0700 Subject: [PATCH 59/77] add teleport.fbx back to avatar/animations compiled and tested in local sandbox but need to test with Jamil in HMD to see that teleport plays correctly for remote viewer --- .../resources/avatar/animations/teleport.fbx | Bin 0 -> 1308144 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 interface/resources/avatar/animations/teleport.fbx diff --git a/interface/resources/avatar/animations/teleport.fbx b/interface/resources/avatar/animations/teleport.fbx new file mode 100644 index 0000000000000000000000000000000000000000..99c950ced6c7006ef0fbb32858558e8756589386 GIT binary patch literal 1308144 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%0Aj8l1dO?9&?QW_ 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�WC!FOd71!c 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

_oF&!_FQ&+tDk}?WkC7 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

>#Gj1)%h53exQ#Dz|8tD8Ce3}!v!36 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


EWpk8 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 Date: Mon, 15 Jul 2019 14:14:24 -0700 Subject: [PATCH 60/77] Remove loading-orb upon killing avatar, in case destructor isn't called --- interface/src/avatar/AvatarManager.cpp | 1 + interface/src/avatar/OtherAvatar.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index c88a934acf..553033f394 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -574,6 +574,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar avatar->die(); queuePhysicsChange(avatar); + avatar->removeOrb(); // remove this avatar's entities from the tree now, if we wait (as we did previously) for this Avatar's destructor // it might not fire until after we create a new instance for the same remote avatar, which creates a race diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 3776d54d9a..8c8c42679b 100755 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -75,6 +75,7 @@ void OtherAvatar::createOrb() { properties.setType(EntityTypes::Sphere); properties.setAlpha(1.0f); properties.setColor(getLoadingOrbColor(_loadingStatus)); + properties.setName("Loading Avatar " + getID().toString()); properties.setPrimitiveMode(PrimitiveMode::LINES); properties.getPulse().setMin(0.5f); properties.getPulse().setMax(1.0f); From 50d9a5388312796ffcdacdeb5145b677c5e7fcca Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 15 Jul 2019 15:03:25 -0700 Subject: [PATCH 61/77] Fix variable name in assert --- libraries/workload/src/workload/RegionState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/workload/src/workload/RegionState.cpp b/libraries/workload/src/workload/RegionState.cpp index 509c00a048..c7fc8219a3 100644 --- a/libraries/workload/src/workload/RegionState.cpp +++ b/libraries/workload/src/workload/RegionState.cpp @@ -30,7 +30,7 @@ void RegionState::run(const workload::WorkloadContextPointer& renderContext, con // inputs[2N + 1] = vector of ids entering region N // // But we only pass inputs for R1 through R3 - assert(inputs.size() == 2 * RegionState::NUM_REGIONS_TRACKED); + assert(inputs.size() == 2 * workload::Region::NUM_TRACKED_REGIONS); // The id's in each vector are sorted in ascending order // because the source vectors are scanned in ascending order. From e896a531132914c4735c9882506eaf76322e0e3c Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Mon, 15 Jul 2019 17:18:38 -0700 Subject: [PATCH 62/77] fix interactive crash --- .../scripting/DesktopScriptingInterface.cpp | 1 - interface/src/ui/InteractiveWindow.cpp | 34 +++++++------------ 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/interface/src/scripting/DesktopScriptingInterface.cpp b/interface/src/scripting/DesktopScriptingInterface.cpp index 678e698033..a1c8e4fc6c 100644 --- a/interface/src/scripting/DesktopScriptingInterface.cpp +++ b/interface/src/scripting/DesktopScriptingInterface.cpp @@ -132,7 +132,6 @@ InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString& } InteractiveWindowPointer DesktopScriptingInterface::createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread) { - // The offscreen surface already validates against non-local QML sources, but we also need to ensure that // if we create top level QML, like dock widgets or other types of QQuickView containing desktop windows // that the source URL is permitted diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index dff1f4dcb5..fc2d8c56bf 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -293,7 +293,11 @@ void InteractiveWindow::close() { if (_dockWidget) { auto window = qApp->getWindow(); - BLOCKING_INVOKE_METHOD(window, "removeDockWidget", Q_ARG(QDockWidget*, _dockWidget.get())); + if (QThread::currentThread() != window->thread()) { + BLOCKING_INVOKE_METHOD(window, "removeDockWidget", Q_ARG(QDockWidget*, _dockWidget.get())); + } else { + window->removeDockWidget(_dockWidget.get()); + } } _dockWidget = nullptr; _qmlWindowProxy = nullptr; @@ -332,10 +336,8 @@ bool InteractiveWindow::isVisible() const { if (!_qmlWindowProxy) { return false; } - QVariant result; - BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), - Q_ARG(QString, INTERACTIVE_WINDOW_VISIBLE_PROPERTY)); - return result.toBool(); + + return _qmlWindowProxy->readProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool(); } glm::vec2 InteractiveWindow::getPosition() const { @@ -343,11 +345,7 @@ glm::vec2 InteractiveWindow::getPosition() const { return {}; } - QVariant result; - BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), - Q_ARG(QString, INTERACTIVE_WINDOW_POSITION_PROPERTY)); - - return toGlm(result.toPointF()); + return toGlm(_qmlWindowProxy->readProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF()); } void InteractiveWindow::setPosition(const glm::vec2& position) { @@ -363,10 +361,7 @@ glm::vec2 InteractiveWindow::getSize() const { return {}; } - QVariant result; - BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), - Q_ARG(QString, INTERACTIVE_WINDOW_SIZE_PROPERTY)); - return toGlm(result.toSize()); + return toGlm(_qmlWindowProxy->readProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize()); } void InteractiveWindow::setSize(const glm::vec2& size) { @@ -382,10 +377,7 @@ QString InteractiveWindow::getTitle() const { return QString(); } - QVariant result; - BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), - Q_ARG(QString, TITLE_PROPERTY)); - return result.toString(); + return _qmlWindowProxy->readProperty(TITLE_PROPERTY).toString(); } void InteractiveWindow::setTitle(const QString& title) { @@ -399,10 +391,8 @@ int InteractiveWindow::getPresentationMode() const { if (!_qmlWindowProxy) { return Virtual; } - QVariant result; - BLOCKING_INVOKE_METHOD(_qmlWindowProxy.get(), "readProperty", Q_RETURN_ARG(QVariant, result), - Q_ARG(QString, PRESENTATION_MODE_PROPERTY)); - return result.toInt(); + + return _qmlWindowProxy->readProperty(PRESENTATION_MODE_PROPERTY).toInt(); } void InteractiveWindow::parentNativeWindowToMainWindow() { From 22a913bee2882aa14733c22c99080db4bc405f1a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 15 Jul 2019 21:10:42 -0700 Subject: [PATCH 63/77] fix bug that caused comfort-mode to be active at all times in HMD --- .../src/display-plugins/hmd/HmdDisplayPlugin.cpp | 15 +++------------ plugins/oculus/src/OculusDisplayPlugin.cpp | 4 ++-- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 9cbf189b38..24c16c1493 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -485,22 +485,13 @@ float HmdDisplayPlugin::stutterRate() const { } float adjustVisionSqueezeRatioForDevice(float visionSqueezeRatio, float visionSqueezeDeviceLow, float visionSqueezeDeviceHigh) { - const float SETTINGS_STEP = 0.2f; // adjusting the slider in preferences changes the ratio by this much - - if (visionSqueezeRatio == 0.0f) { + if (visionSqueezeRatio <= 0.0f) { return 0.0f; } float deviceRange = visionSqueezeDeviceHigh - visionSqueezeDeviceLow; - - if (visionSqueezeRatio <= SETTINGS_STEP) { - // lowest "enabled" setting -- without this special case the user doesn't see anything on the lowest setting - float scaleFactor = (visionSqueezeRatio == SETTINGS_STEP) ? 0.24f : 0.18f; // these magic values were picked through experimentation - return deviceRange * scaleFactor + visionSqueezeDeviceLow; - } else { - const float SQUEEZE_ADJUSTMENT = 0.75f; // magic number picked through experimentation - return deviceRange * (SQUEEZE_ADJUSTMENT * visionSqueezeRatio) + visionSqueezeDeviceLow; - } + const float SQUEEZE_ADJUSTMENT = 0.75f; // magic number picked through experimentation + return deviceRange * (SQUEEZE_ADJUSTMENT * visionSqueezeRatio) + visionSqueezeDeviceLow; } void HmdDisplayPlugin::updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY, diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index b2fc6881f4..a2dc7be325 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -55,9 +55,9 @@ void OculusDisplayPlugin::init() { // Different HMDs end up showing the squeezed-vision egg as different sizes. These values // attempt to make them appear the same. - _visionSqueezeDeviceLowX = 0.8f; + _visionSqueezeDeviceLowX = 0.7f; _visionSqueezeDeviceHighX = 0.98f; - _visionSqueezeDeviceLowY = 0.8f; + _visionSqueezeDeviceLowY = 0.7f; _visionSqueezeDeviceHighY = 0.9f; emit deviceConnected(getName()); From 53ec19dd57d2864b94f1f3523e1f1c91aac8e750 Mon Sep 17 00:00:00 2001 From: milad Date: Tue, 16 Jul 2019 10:27:56 -0700 Subject: [PATCH 64/77] removed session display name from nametag --- .../resources/modules/nameTagListManager.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js b/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js index 216767c1cb..407af0e7b3 100644 --- a/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js +++ b/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js @@ -253,11 +253,7 @@ function getCorrectName(uuid) { var avatar = _this.avatars[uuid]; var avatarInfo = avatar.avatarInfo; - var displayNameToUse = avatarInfo.sessionDisplayName.trim(); - - if (displayNameToUse === "") { - displayNameToUse = avatarInfo.displayName.trim(); - } + var displayNameToUse = avatarInfo.displayName.trim(); if (displayNameToUse === "") { displayNameToUse = "anonymous"; From 6425c6883613aebe9167f20a44b2388b7237c017 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Tue, 16 Jul 2019 10:48:51 -0700 Subject: [PATCH 65/77] fix for self assignment warning --- libraries/animation/src/AnimInverseKinematics.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index ed3d5d67d6..8d98f9c775 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -431,7 +431,6 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const constrained = constraint->apply(tipRelativeRotation); if (constrained) { tipOrientation = tipParentOrientation * tipRelativeRotation; - tipRelativeRotation = tipRelativeRotation; } } From a31c83400948b7cd079ef03a253a9e5f756f3db0 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Tue, 16 Jul 2019 10:49:37 -0700 Subject: [PATCH 66/77] macos include fix. On macos with a case sensitive harddrive this include fails. Change it to the more standard form. --- plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp index e6b555443f..a8ad10a9a0 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp @@ -11,7 +11,7 @@ #include -#include +#include #include #include #include From 77ec048947fa47d24aa0166b96cbfdb377235510 Mon Sep 17 00:00:00 2001 From: milad Date: Tue, 16 Jul 2019 12:23:32 -0700 Subject: [PATCH 67/77] added change to the statusIndicator for the same thing --- .../simplifiedStatusIndicator/simplifiedStatusIndicator.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js b/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js index 789c497104..c064e2d138 100644 --- a/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js +++ b/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js @@ -60,10 +60,8 @@ function simplifiedStatusIndicator(properties) { var queryParamString = "type=heartbeat"; queryParamString += "&username=" + AccountServices.username; - var displayNameToSend = MyAvatar.sessionDisplayName; - if (displayNameToSend === "") { - displayNameToSend = MyAvatar.displayName; - } + var displayNameToSend = MyAvatar.displayName; + queryParamString += "&displayName=" + displayNameToSend; queryParamString += "&status=" + currentStatus; queryParamString += "&organization=" + location.hostname; From 11f47ddeedeff34882c13728a41dcd0781d7a01e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 16 Jul 2019 13:42:39 -0700 Subject: [PATCH 68/77] BUGZ-753: bad skyboxes on intel GPUs --- libraries/gl/src/gl/GLHelpers.cpp | 17 ++++++++++++++++- libraries/gl/src/gl/GLHelpers.h | 1 + tests-manual/gpu/CMakeLists.txt | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp index 7b47736a3d..c9f17b686d 100644 --- a/libraries/gl/src/gl/GLHelpers.cpp +++ b/libraries/gl/src/gl/GLHelpers.cpp @@ -26,13 +26,19 @@ size_t evalGLFormatSwapchainPixelSize(const QSurfaceFormat& format) { return pixelSize; } +static bool FORCE_DISABLE_OPENGL_45 = false; + +void gl::setDisableGl45(bool disable) { + FORCE_DISABLE_OPENGL_45 = disable; +} + bool gl::disableGl45() { #if defined(USE_GLES) return false; #else static const QString DEBUG_FLAG("HIFI_DISABLE_OPENGL_45"); static bool disableOpenGL45 = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG); - return disableOpenGL45; + return FORCE_DISABLE_OPENGL_45 || disableOpenGL45; #endif } @@ -202,6 +208,15 @@ uint16_t gl::getAvailableVersion() { return; } gl::initModuleGl(); + + std::string glvendor{ (const char*)glGetString(GL_VENDOR) }; + std::transform(glvendor.begin(), glvendor.end(), glvendor.begin(), ::tolower); + + // Intel has *notoriously* buggy DSA implementations, especially around cubemaps + if (std::string::npos != glvendor.find("intel")) { + gl::setDisableGl45(true); + } + wglMakeCurrent(0, 0); hGLRC.reset(); if (!wglChoosePixelFormatARB || !wglCreateContextAttribsARB) { diff --git a/libraries/gl/src/gl/GLHelpers.h b/libraries/gl/src/gl/GLHelpers.h index 95c3b6a5c2..c09f9d4963 100644 --- a/libraries/gl/src/gl/GLHelpers.h +++ b/libraries/gl/src/gl/GLHelpers.h @@ -55,6 +55,7 @@ namespace gl { bool checkGLErrorDebug(const char* name); bool disableGl45(); + void setDisableGl45(bool disable); uint16_t getTargetVersion(); diff --git a/tests-manual/gpu/CMakeLists.txt b/tests-manual/gpu/CMakeLists.txt index 2b04bdc3f2..6e3781acff 100644 --- a/tests-manual/gpu/CMakeLists.txt +++ b/tests-manual/gpu/CMakeLists.txt @@ -6,7 +6,7 @@ set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") link_hifi_libraries( shared task networking gl ktx shaders gpu procedural octree image - graphics model-networking fbx hfm animation + graphics model-networking fbx hfm animation material-networking script-engine render render-utils ${PLATFORM_GL_BACKEND} ) From 1cd136f17832ddce5124ff16aab6b91c0e92a145 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 16 Jul 2019 15:15:08 -0700 Subject: [PATCH 69/77] Fix BUGZ-814 in VR mode: Add a top margin to tablet graphics settings --- .../resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml index f7c82c90a1..8634648d17 100644 --- a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml +++ b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml @@ -31,6 +31,7 @@ Item { anchors.right: parent.right anchors.rightMargin: 26 anchors.top: parent.top + anchors.topMargin: HMD.active ? 80 : 0 spacing: 8 ColumnLayout { From 05d896f3de1945fd3713dbf335ba06f0c0442c6f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 10 Jul 2019 17:45:35 -0700 Subject: [PATCH 70/77] fix SafeLanding failure mode when first sequence number not 0 --- interface/src/Application.cpp | 3 +- .../src/octree/OctreePacketProcessor.cpp | 21 ++++-- interface/src/octree/OctreePacketProcessor.h | 2 + interface/src/octree/SafeLanding.cpp | 68 +++++++++++-------- interface/src/octree/SafeLanding.h | 26 ++++--- 5 files changed, 75 insertions(+), 45 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d20574bdaa..cd7bb36763 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6245,6 +6245,7 @@ void Application::tryToEnablePhysics() { // We keep physics disabled until we've received a full scene and everything near the avatar in that // scene is ready to compute its collision shape. if (getMyAvatar()->isReadyForPhysics()) { + _octreeProcessor.resetSafeLanding(); _physicsEnabled = true; setIsInterstitialMode(false); getMyAvatar()->updateMotionBehaviorFromMenu(); @@ -7316,7 +7317,7 @@ void Application::nodeKilled(SharedNodePointer node) { _octreeProcessor.nodeKilled(node); _entityEditSender.nodeKilled(node); - + if (node->getType() == NodeType::AudioMixer) { QMetaObject::invokeMethod(DependencyManager::get().data(), "audioMixerKilled"); } else if (node->getType() == NodeType::EntityServer) { diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index c6f908e039..a44774540a 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -114,7 +114,11 @@ void OctreePacketProcessor::processPacket(QSharedPointer messag if (renderer) { renderer->processDatagram(*message, sendingNode); if (_safeLanding && _safeLanding->isTracking()) { - _safeLanding->addToSequence(renderer->getLastOctreeMessageSequence()); + OCTREE_PACKET_SEQUENCE thisSequence = renderer->getLastOctreeMessageSequence(); + _safeLanding->addToSequence(thisSequence); + if (_safeLandingSequenceStart == SafeLanding::INVALID_SEQUENCE) { + _safeLandingSequenceStart = thisSequence; + } } } } @@ -122,10 +126,10 @@ void OctreePacketProcessor::processPacket(QSharedPointer messag case PacketType::EntityQueryInitialResultsComplete: { // Read sequence # - OCTREE_PACKET_SEQUENCE completionNumber; - message->readPrimitive(&completionNumber); - if (_safeLanding) { - _safeLanding->finishSequence(0, completionNumber); + if (_safeLanding && _safeLanding->isTracking()) { + OCTREE_PACKET_SEQUENCE completionNumber; + message->readPrimitive(&completionNumber); + _safeLanding->finishSequence(_safeLandingSequenceStart, completionNumber); } } break; @@ -153,6 +157,13 @@ void OctreePacketProcessor::stopSafeLanding() { } } +void OctreePacketProcessor::resetSafeLanding() { + if (_safeLanding) { + _safeLanding->reset(); + } + _safeLandingSequenceStart = SafeLanding::INVALID_SEQUENCE; +} + bool OctreePacketProcessor::safeLandingIsActive() const { return _safeLanding && _safeLanding->isTracking(); } diff --git a/interface/src/octree/OctreePacketProcessor.h b/interface/src/octree/OctreePacketProcessor.h index eacc15f62d..d56b7e0e35 100644 --- a/interface/src/octree/OctreePacketProcessor.h +++ b/interface/src/octree/OctreePacketProcessor.h @@ -28,6 +28,7 @@ public: void startSafeLanding(); void updateSafeLanding(); void stopSafeLanding(); + void resetSafeLanding(); bool safeLandingIsActive() const; bool safeLandingIsComplete() const; @@ -43,6 +44,7 @@ private slots: void handleOctreePacket(QSharedPointer message, SharedNodePointer senderNode); private: + OCTREE_PACKET_SEQUENCE _safeLandingSequenceStart { SafeLanding::INVALID_SEQUENCE }; std::unique_ptr _safeLanding; }; #endif // hifi_OctreePacketProcessor_h diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 80ca0e5398..2e2a43859c 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -17,7 +17,6 @@ #include "InterfaceLogging.h" #include "Application.h" -const int SafeLanding::SEQUENCE_MODULO = std::numeric_limits::max() + 1; CalculateEntityLoadingPriority SafeLanding::entityLoadingOperatorElevateCollidables = [](const EntityItem& entityItem) { const int COLLIDABLE_ENTITY_PRIORITY = 10.0f; @@ -25,8 +24,8 @@ CalculateEntityLoadingPriority SafeLanding::entityLoadingOperatorElevateCollidab }; namespace { - template bool lessThanWraparound(int a, int b) { - constexpr int MAX_T_VALUE = std::numeric_limits::max(); + template bool lessThanWraparound(int32_t a, int32_t b) { + constexpr int32_t MAX_T_VALUE = std::numeric_limits::max(); if (b <= a) { b += MAX_T_VALUE; } @@ -34,7 +33,7 @@ namespace { } } -bool SafeLanding::SequenceLessThan::operator()(const int& a, const int& b) const { +bool SafeLanding::SequenceLessThan::operator()(const OCTREE_PACKET_SEQUENCE& a, const OCTREE_PACKET_SEQUENCE& b) const { return lessThanWraparound(a, b); } @@ -46,8 +45,8 @@ void SafeLanding::startTracking(QSharedPointer entityTreeRen _entityTreeRenderer = entityTreeRenderer; _trackedEntities.clear(); _maxTrackedEntityCount = 0; - _initialStart = INVALID_SEQUENCE; - _initialEnd = INVALID_SEQUENCE; + _sequenceStart = SafeLanding::INVALID_SEQUENCE; + _sequenceEnd = SafeLanding::INVALID_SEQUENCE; _sequenceNumbers.clear(); _trackingEntities = true; _startTime = usecTimestampNow(); @@ -72,7 +71,7 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) { if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) { _trackedEntities.emplace(entityID, entity); - int trackedEntityCount = (int)_trackedEntities.size(); + int32_t trackedEntityCount = (int32_t)_trackedEntities.size(); if (trackedEntityCount > _maxTrackedEntityCount) { _maxTrackedEntityCount = trackedEntityCount; _trackedEntityStabilityCount = 0; @@ -87,15 +86,15 @@ void SafeLanding::deleteTrackedEntity(const EntityItemID& entityID) { _trackedEntities.erase(entityID); } -void SafeLanding::finishSequence(int first, int last) { +void SafeLanding::finishSequence(OCTREE_PACKET_SEQUENCE first, OCTREE_PACKET_SEQUENCE last) { Locker lock(_lock); if (_trackingEntities) { - _initialStart = first; - _initialEnd = last; + _sequenceStart = first; + _sequenceEnd = last; } } -void SafeLanding::addToSequence(int sequenceNumber) { +void SafeLanding::addToSequence(OCTREE_PACKET_SEQUENCE sequenceNumber) { Locker lock(_lock); _sequenceNumbers.insert(sequenceNumber); } @@ -135,14 +134,15 @@ void SafeLanding::updateTracking() { if (_trackedEntities.empty()) { // no more tracked entities --> check sequenceNumbers - if (_initialStart != INVALID_SEQUENCE) { + if (_sequenceStart != SafeLanding::INVALID_SEQUENCE) { bool shouldStop = false; { Locker lock(_lock); - int sequenceSize = _initialStart <= _initialEnd ? _initialEnd - _initialStart: - _initialEnd + SEQUENCE_MODULO - _initialStart; - auto startIter = _sequenceNumbers.find(_initialStart); - auto endIter = _sequenceNumbers.find(_initialEnd - 1); + int32_t sequenceSize = _sequenceStart < _sequenceEnd ? + (int32_t)(_sequenceEnd - _sequenceStart) : + (int32_t)((SafeLanding::MAX_SEQUENCE - _sequenceStart) + _sequenceEnd + 1); // with rollover + auto startIter = _sequenceNumbers.find(_sequenceStart); + auto endIter = _sequenceNumbers.find(_sequenceEnd - 1); bool missingSequenceNumbers = qApp->isMissingSequenceNumbers(); shouldStop = (sequenceSize == 0 || @@ -171,19 +171,27 @@ void SafeLanding::stopTracking() { EntityTreeRenderer::setEntityLoadingPriorityFunction(_prevEntityLoadingPriorityOperator); } +void SafeLanding::reset() { + _trackingEntities = false; + _trackedEntities.clear(); + _maxTrackedEntityCount = 0; + _sequenceStart = SafeLanding::INVALID_SEQUENCE; + _sequenceEnd = SafeLanding::INVALID_SEQUENCE; +} + bool SafeLanding::trackingIsComplete() const { - return !_trackingEntities && (_initialStart != INVALID_SEQUENCE); + return !_trackingEntities && (_sequenceStart != SafeLanding::INVALID_SEQUENCE); } float SafeLanding::loadingProgressPercentage() { Locker lock(_lock); - static const int MINIMUM_TRACKED_ENTITY_STABILITY_COUNT = 15; float entityReadyPercentage = 0.0f; if (_maxTrackedEntityCount > 0) { entityReadyPercentage = ((_maxTrackedEntityCount - _trackedEntities.size()) / (float)_maxTrackedEntityCount); } + constexpr int32_t MINIMUM_TRACKED_ENTITY_STABILITY_COUNT = 15; if (_trackedEntityStabilityCount < MINIMUM_TRACKED_ENTITY_STABILITY_COUNT) { entityReadyPercentage *= 0.20f; } @@ -226,20 +234,24 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) { } void SafeLanding::debugDumpSequenceIDs() const { - int p = -1; qCDebug(interfaceapp) << "Sequence set size:" << _sequenceNumbers.size(); - for (auto s: _sequenceNumbers) { - if (p == -1) { - p = s; - qCDebug(interfaceapp) << "First:" << s; - } else { + + auto itr = _sequenceNumbers.begin(); + OCTREE_PACKET_SEQUENCE p = SafeLanding::INVALID_SEQUENCE; + if (itr != _sequenceNumbers.end()) { + p = (*itr); + qCDebug(interfaceapp) << "First:" << (int32_t)p; + ++itr; + while (itr != _sequenceNumbers.end()) { + OCTREE_PACKET_SEQUENCE s = *itr; if (s != p + 1) { - qCDebug(interfaceapp) << "Gap from" << p << "to" << s << "(exclusive)"; + qCDebug(interfaceapp) << "Gap from" << (int32_t)p << "to" << (int32_t)s << "(exclusive)"; p = s; } + ++itr; + } + if (p != SafeLanding::INVALID_SEQUENCE) { + qCDebug(interfaceapp) << "Last:" << p; } } - if (p != -1) { - qCDebug(interfaceapp) << "Last:" << p; - } } diff --git a/interface/src/octree/SafeLanding.h b/interface/src/octree/SafeLanding.h index 87dac16ba3..00473f6fc8 100644 --- a/interface/src/octree/SafeLanding.h +++ b/interface/src/octree/SafeLanding.h @@ -17,6 +17,8 @@ #include #include +#include + #include "EntityItem.h" #include "EntityDynamicInterface.h" @@ -27,14 +29,18 @@ class EntityItemID; class SafeLanding : public QObject { public: + static constexpr OCTREE_PACKET_SEQUENCE MAX_SEQUENCE = std::numeric_limits::max(); + static constexpr OCTREE_PACKET_SEQUENCE INVALID_SEQUENCE = MAX_SEQUENCE; // not technically invalid, but close enough + void startTracking(QSharedPointer entityTreeRenderer); void updateTracking(); void stopTracking(); + void reset(); bool isTracking() const { return _trackingEntities; } bool trackingIsComplete() const; - void finishSequence(int first, int last); // 'last' exclusive. - void addToSequence(int sequenceNumber); + void finishSequence(OCTREE_PACKET_SEQUENCE first, OCTREE_PACKET_SEQUENCE last); // 'last' exclusive. + void addToSequence(OCTREE_PACKET_SEQUENCE sequenceNumber); float loadingProgressPercentage(); private slots: @@ -52,24 +58,22 @@ private: using EntityMap = std::map; EntityMap _trackedEntities; - static constexpr int INVALID_SEQUENCE = -1; - int _initialStart { INVALID_SEQUENCE }; - int _initialEnd { INVALID_SEQUENCE }; - int _maxTrackedEntityCount { 0 }; - int _trackedEntityStabilityCount { 0 }; + OCTREE_PACKET_SEQUENCE _sequenceStart { INVALID_SEQUENCE }; + OCTREE_PACKET_SEQUENCE _sequenceEnd { INVALID_SEQUENCE }; + int32_t _maxTrackedEntityCount { 0 }; + int32_t _trackedEntityStabilityCount { 0 }; quint64 _startTime { 0 }; struct SequenceLessThan { - bool operator()(const int& a, const int& b) const; + bool operator()(const OCTREE_PACKET_SEQUENCE& a, const OCTREE_PACKET_SEQUENCE& b) const; }; - std::set _sequenceNumbers; + using SequenceSet = std::set; + SequenceSet _sequenceNumbers; static CalculateEntityLoadingPriority entityLoadingOperatorElevateCollidables; CalculateEntityLoadingPriority _prevEntityLoadingPriorityOperator { nullptr }; - - static const int SEQUENCE_MODULO; }; #endif // hifi_SafeLanding_h From b0f297e696a9d49280710bd8e1522ff05900333b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 17 Jul 2019 11:20:38 -0700 Subject: [PATCH 71/77] wait for SafeLanding to start before starting octreeQuery --- interface/src/Application.cpp | 12 +++++++----- interface/src/octree/SafeLanding.cpp | 20 +++++++++++--------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cd7bb36763..ad38599dcf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5986,6 +5986,7 @@ void Application::resetPhysicsReadyInformation() { _gpuTextureMemSizeStabilityCount = 0; _gpuTextureMemSizeAtLastCheck = 0; _physicsEnabled = false; + _octreeProcessor.stopSafeLanding(); } void Application::reloadResourceCaches() { @@ -6981,13 +6982,16 @@ int Application::sendNackPackets() { } void Application::queryOctree(NodeType_t serverType, PacketType packetType) { - if (!_settingsLoaded) { return; // bail early if settings are not loaded } const bool isModifiedQuery = !_physicsEnabled; if (isModifiedQuery) { + if (!_octreeProcessor.safeLandingIsActive()) { + // don't send the octreeQuery until SafeLanding knows it has started + return; + } // Create modified view that is a simple sphere. bool interstitialModeEnabled = DependencyManager::get()->getDomainHandler().getInterstitialModeEnabled(); @@ -7210,7 +7214,6 @@ void Application::clearDomainOctreeDetails(bool clearAll) { void Application::domainURLChanged(QUrl domainURL) { // disable physics until we have enough information about our new location to not cause craziness. - resetPhysicsReadyInformation(); setIsServerlessMode(domainURL.scheme() != URL_SCHEME_HIFI); if (isServerlessMode()) { loadServerlessDomain(domainURL); @@ -7220,7 +7223,6 @@ void Application::domainURLChanged(QUrl domainURL) { void Application::goToErrorDomainURL(QUrl errorDomainURL) { // disable physics until we have enough information about our new location to not cause craziness. - resetPhysicsReadyInformation(); setIsServerlessMode(errorDomainURL.scheme() != URL_SCHEME_HIFI); if (isServerlessMode()) { loadErrorDomain(errorDomainURL); @@ -7237,12 +7239,12 @@ void Application::resettingDomain() { void Application::nodeAdded(SharedNodePointer node) { if (node->getType() == NodeType::EntityServer) { if (_failedToConnectToEntityServer && !_entityServerConnectionTimer.isActive()) { - _failedToConnectToEntityServer = false; _octreeProcessor.stopSafeLanding(); - _octreeProcessor.startSafeLanding(); + _failedToConnectToEntityServer = false; } else if (_entityServerConnectionTimer.isActive()) { _entityServerConnectionTimer.stop(); } + _octreeProcessor.startSafeLanding(); _entityServerConnectionTimer.setInterval(ENTITY_SERVER_CONNECTION_TIMEOUT); _entityServerConnectionTimer.start(); } diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 2e2a43859c..6f715ea033 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -159,16 +159,18 @@ void SafeLanding::updateTracking() { void SafeLanding::stopTracking() { Locker lock(_lock); - _trackingEntities = false; - if (_entityTreeRenderer) { - auto entityTree = _entityTreeRenderer->getTree(); - disconnect(std::const_pointer_cast(entityTree).get(), - &EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity); - disconnect(std::const_pointer_cast(entityTree).get(), - &EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity); - _entityTreeRenderer.reset(); + if (_trackingEntities) { + _trackingEntities = false; + if (_entityTreeRenderer) { + auto entityTree = _entityTreeRenderer->getTree(); + disconnect(std::const_pointer_cast(entityTree).get(), + &EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity); + disconnect(std::const_pointer_cast(entityTree).get(), + &EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity); + _entityTreeRenderer.reset(); + } + EntityTreeRenderer::setEntityLoadingPriorityFunction(_prevEntityLoadingPriorityOperator); } - EntityTreeRenderer::setEntityLoadingPriorityFunction(_prevEntityLoadingPriorityOperator); } void SafeLanding::reset() { From 4f9d62696c118da4c0afa9e66d2a64c4b876ebcd Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Wed, 17 Jul 2019 12:58:17 -0700 Subject: [PATCH 72/77] DEV-262 - Improve logging on failure to load resource --- libraries/networking/src/ResourceCache.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index ef8a7b577d..88e6b14ec7 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -842,7 +842,8 @@ bool Resource::handleFailedRequest(ResourceRequest::Result result) { // FALLTHRU default: { _attemptsRemaining = 0; - qCDebug(networking) << "Error loading, attempt:" << _attempts << "attemptsRemaining:" << _attemptsRemaining; + QMetaEnum metaEnum = QMetaEnum::fromType(); + qCDebug(networking) << "Error loading:" << metaEnum.valueToKey(result) << "resource:" << _url.toString(); auto error = (result == ResourceRequest::Timeout) ? QNetworkReply::TimeoutError : QNetworkReply::UnknownNetworkError; emit failed(error); From 63b3d666f950dcdde24bf74fef304a28ea24350f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 17 Jul 2019 13:57:08 -0700 Subject: [PATCH 73/77] simplify rollover logic for SafeLanding sequence size calculation --- interface/src/octree/SafeLanding.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 6f715ea033..ed779787c9 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -138,9 +138,7 @@ void SafeLanding::updateTracking() { bool shouldStop = false; { Locker lock(_lock); - int32_t sequenceSize = _sequenceStart < _sequenceEnd ? - (int32_t)(_sequenceEnd - _sequenceStart) : - (int32_t)((SafeLanding::MAX_SEQUENCE - _sequenceStart) + _sequenceEnd + 1); // with rollover + auto sequenceSize = _sequenceEnd - _sequenceStart; // this works even in rollover case auto startIter = _sequenceNumbers.find(_sequenceStart); auto endIter = _sequenceNumbers.find(_sequenceEnd - 1); From a3b8ded56a1b635d06b0a58f647c44cf1ce06316 Mon Sep 17 00:00:00 2001 From: milad Date: Wed, 17 Jul 2019 14:17:58 -0700 Subject: [PATCH 74/77] changed sessionDisplayName logic --- .../simplifiedUI/avatarApp/components/DisplayNameHeader.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/avatarApp/components/DisplayNameHeader.qml b/interface/resources/qml/hifi/simplifiedUI/avatarApp/components/DisplayNameHeader.qml index becbd8ca61..8938fb9b0b 100644 --- a/interface/resources/qml/hifi/simplifiedUI/avatarApp/components/DisplayNameHeader.qml +++ b/interface/resources/qml/hifi/simplifiedUI/avatarApp/components/DisplayNameHeader.qml @@ -91,7 +91,7 @@ Item { SimplifiedControls.TextField { id: myDisplayNameText - text: MyAvatar.sessionDisplayName === "" ? MyAvatar.displayName : MyAvatar.sessionDisplayName + text: MyAvatar.displayName maximumLength: 256 clip: true selectByMouse: true From 7b7414dead363a6d130e134654cd9ee5c1855012 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 17 Jul 2019 17:04:12 -0700 Subject: [PATCH 75/77] revert optimization that would skip read from packet --- interface/src/octree/OctreePacketProcessor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index a44774540a..bc3c1afdd5 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -126,9 +126,9 @@ void OctreePacketProcessor::processPacket(QSharedPointer messag case PacketType::EntityQueryInitialResultsComplete: { // Read sequence # + OCTREE_PACKET_SEQUENCE completionNumber; + message->readPrimitive(&completionNumber); if (_safeLanding && _safeLanding->isTracking()) { - OCTREE_PACKET_SEQUENCE completionNumber; - message->readPrimitive(&completionNumber); _safeLanding->finishSequence(_safeLandingSequenceStart, completionNumber); } } break; From 03b8de1ee724ae8238774a29d315b248c5dde4aa Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 18 Jul 2019 08:43:39 -0700 Subject: [PATCH 76/77] Fix create window being destroyed when closed --- interface/resources/qml/InteractiveWindow.qml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/InteractiveWindow.qml b/interface/resources/qml/InteractiveWindow.qml index 9136de9dcf..b27668f70c 100644 --- a/interface/resources/qml/InteractiveWindow.qml +++ b/interface/resources/qml/InteractiveWindow.qml @@ -30,7 +30,6 @@ Windows.Window { signal selfDestruct(); - property var flags: 0; property var additionalFlags: 0; property var overrideFlags: 0; @@ -158,8 +157,7 @@ Windows.Window { if (Qt.platform.os !== "windows" && (root.additionalFlags & Desktop.ALWAYS_ON_TOP)) { nativeWindowFlags |= Qt.WindowStaysOnTopHint; } - root.flags = root.overrideFlags || nativeWindowFlags; - nativeWindow.flags = root.flags; + nativeWindow.flags = root.overrideFlags || nativeWindowFlags; nativeWindow.x = interactiveWindowPosition.x; nativeWindow.y = interactiveWindowPosition.y; @@ -317,7 +315,7 @@ Windows.Window { // set invisible on close, to make it not re-appear unintended after switching PresentationMode interactiveWindowVisible = false; - if ((root.flags & Desktop.CLOSE_BUTTON_HIDES) !== Desktop.CLOSE_BUTTON_HIDES) { + if ((root.additionalFlags & Desktop.CLOSE_BUTTON_HIDES) !== Desktop.CLOSE_BUTTON_HIDES) { selfDestruct(); } } From 510c92291217baa35e0537dede3bf5bbe1583d39 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 19 Jul 2019 11:34:14 -0700 Subject: [PATCH 77/77] Fix BUGZ-1062: Set the correct Settings value for bubble tools --- interface/src/ui/AvatarInputs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/AvatarInputs.cpp b/interface/src/ui/AvatarInputs.cpp index bae6621fb2..b9a1fc441f 100644 --- a/interface/src/ui/AvatarInputs.cpp +++ b/interface/src/ui/AvatarInputs.cpp @@ -94,7 +94,7 @@ void AvatarInputs::setShowBubbleTools(bool showBubbleTools) { return; _showBubbleTools = showBubbleTools; - showBubbleToolsSetting.set(_showAudioTools); + showBubbleToolsSetting.set(_showBubbleTools); emit showBubbleToolsChanged(_showBubbleTools); }