diff --git a/examples/21-deferred/deferred.cpp b/examples/21-deferred/deferred.cpp index a917cbe95..f38ea146c 100644 --- a/examples/21-deferred/deferred.cpp +++ b/examples/21-deferred/deferred.cpp @@ -281,6 +281,17 @@ public: m_debugProgram = loadProgram("vs_deferred_debug", "fs_deferred_debug"); m_lineProgram = loadProgram("vs_deferred_debug_line", "fs_deferred_debug_line"); + m_useTArray = false; + + if (0 != (BGFX_CAPS_TEXTURE_2D_ARRAY & bgfx::getCaps()->supported) ) + { + m_lightTaProgram = loadProgram("vs_deferred_light", "fs_deferred_light_ta"); + } + else + { + m_lightTaProgram = BGFX_INVALID_HANDLE; + } + // Load diffuse texture. m_textureColor = loadTexture("textures/fieldstone-rgba.dds"); @@ -290,8 +301,8 @@ public: m_gbufferTex[0].idx = bgfx::kInvalidHandle; m_gbufferTex[1].idx = bgfx::kInvalidHandle; m_gbufferTex[2].idx = bgfx::kInvalidHandle; - m_gbuffer.idx = bgfx::kInvalidHandle; - m_lightBuffer.idx = bgfx::kInvalidHandle; + m_gbuffer.idx = bgfx::kInvalidHandle; + m_lightBuffer.idx = bgfx::kInvalidHandle; // Imgui. imguiCreate(); @@ -337,6 +348,12 @@ public: bgfx::destroy(m_geomProgram); bgfx::destroy(m_lightProgram); + + if (bgfx::isValid(m_lightTaProgram) ) + { + bgfx::destroy(m_lightTaProgram); + } + bgfx::destroy(m_combineProgram); bgfx::destroy(m_debugProgram); bgfx::destroy(m_lineProgram); @@ -402,19 +419,24 @@ public: } else { - if (m_oldWidth != m_width - || m_oldHeight != m_height - || m_oldReset != m_reset + if (m_oldWidth != m_width + || m_oldHeight != m_height + || m_oldReset != m_reset + || m_oldUseTArray != m_useTArray || !bgfx::isValid(m_gbuffer) ) { // Recreate variable size render targets when resolution changes. - m_oldWidth = m_width; - m_oldHeight = m_height; - m_oldReset = m_reset; + m_oldWidth = m_width; + m_oldHeight = m_height; + m_oldReset = m_reset; + m_oldUseTArray = m_useTArray; if (bgfx::isValid(m_gbuffer) ) { bgfx::destroy(m_gbuffer); + m_gbufferTex[0].idx = bgfx::kInvalidHandle; + m_gbufferTex[1].idx = bgfx::kInvalidHandle; + m_gbufferTex[2].idx = bgfx::kInvalidHandle; } const uint64_t tsFlags = 0 @@ -425,10 +447,27 @@ public: | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP ; - m_gbufferTex[0] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::BGRA8, tsFlags); - m_gbufferTex[1] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::BGRA8, tsFlags); + + bgfx::Attachment at[3]; + + if (m_useTArray) + { + m_gbufferTex[0] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 2, bgfx::TextureFormat::BGRA8, tsFlags); + at[0].init(m_gbufferTex[0], bgfx::Access::Write, 0); + at[1].init(m_gbufferTex[0], bgfx::Access::Write, 1); + } + else + { + m_gbufferTex[0] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::BGRA8, tsFlags); + m_gbufferTex[1] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::BGRA8, tsFlags); + at[0].init(m_gbufferTex[0]); + at[1].init(m_gbufferTex[1]); + } + m_gbufferTex[2] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::D24S8, tsFlags); - m_gbuffer = bgfx::createFrameBuffer(BX_COUNTOF(m_gbufferTex), m_gbufferTex, true); + at[2].init(m_gbufferTex[2]); + + m_gbuffer = bgfx::createFrameBuffer(BX_COUNTOF(at), at, true); if (bgfx::isValid(m_lightBuffer) ) { @@ -454,6 +493,16 @@ public: ImGui::SliderInt("Num lights", &m_numLights, 1, 2048); ImGui::Checkbox("Show G-Buffer.", &m_showGBuffer); ImGui::Checkbox("Show light scissor.", &m_showScissorRects); + + if (bgfx::isValid(m_lightTaProgram) ) + { + ImGui::Checkbox("Use texture array frame buffer.", &m_useTArray); + } + else + { + ImGui::Text("Texture array frame buffer is not supported."); + } + ImGui::Checkbox("Animate mesh.", &m_animateMesh); ImGui::SliderFloat("Anim.speed", &m_lightAnimationSpeed, 0.0f, 0.4f); @@ -668,7 +717,7 @@ public: | BGFX_STATE_BLEND_ADD ); screenSpaceQuad( (float)m_width, (float)m_height, s_texelHalf, m_caps->originBottomLeft); - bgfx::submit(RENDER_PASS_LIGHT_ID, m_lightProgram); + bgfx::submit(RENDER_PASS_LIGHT_ID, bgfx::isValid(m_lightTaProgram) && m_useTArray ? m_lightTaProgram : m_lightProgram); } } @@ -691,10 +740,10 @@ public: { float mtx[16]; bx::mtxSRT(mtx - , aspectRatio, 1.0f, 1.0f - , 0.0f, 0.0f, 0.0f - , -7.9f - BX_COUNTOF(m_gbufferTex)*0.1f*0.5f + ii*2.1f*aspectRatio, 4.0f, 0.0f - ); + , aspectRatio, 1.0f, 1.0f + , 0.0f, 0.0f, 0.0f + , -7.9f - BX_COUNTOF(m_gbufferTex)*0.1f*0.5f + ii*2.1f*aspectRatio, 4.0f, 0.0f + ); bgfx::setTransform(mtx); bgfx::setVertexBuffer(0, m_vbh); @@ -734,6 +783,7 @@ public: bgfx::ProgramHandle m_geomProgram; bgfx::ProgramHandle m_lightProgram; + bgfx::ProgramHandle m_lightTaProgram; bgfx::ProgramHandle m_combineProgram; bgfx::ProgramHandle m_debugProgram; bgfx::ProgramHandle m_lineProgram; @@ -753,6 +803,9 @@ public: uint32_t m_oldHeight; uint32_t m_oldReset; + bool m_useTArray; + bool m_oldUseTArray; + int32_t m_scrollArea; int32_t m_numLights; float m_lightAnimationSpeed; diff --git a/examples/21-deferred/fs_deferred_light_ta.sc b/examples/21-deferred/fs_deferred_light_ta.sc new file mode 100644 index 000000000..91180c0d0 --- /dev/null +++ b/examples/21-deferred/fs_deferred_light_ta.sc @@ -0,0 +1,91 @@ +$input v_texcoord0 + +/* + * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "../common/common.sh" + +SAMPLER2DARRAY(s_normal, 0); +SAMPLER2D(s_depth, 1); + +uniform vec4 u_lightPosRadius[1]; +uniform vec4 u_lightRgbInnerR[1]; +uniform mat4 u_mtx; + +vec2 blinn(vec3 _lightDir, vec3 _normal, vec3 _viewDir) +{ + float ndotl = dot(_normal, _lightDir); + vec3 reflected = _lightDir - 2.0*ndotl*_normal; // reflect(_lightDir, _normal); + float rdotv = dot(reflected, _viewDir); + return vec2(ndotl, rdotv); +} + +float fresnel(float _ndotl, float _bias, float _pow) +{ + float facing = (1.0 - _ndotl); + return max(_bias + (1.0 - _bias) * pow(facing, _pow), 0.0); +} + +vec4 lit(float _ndotl, float _rdotv, float _m) +{ + float diff = max(0.0, _ndotl); + float spec = step(0.0, _ndotl) * max(0.0, _rdotv * _m); + return vec4(1.0, diff, spec, 1.0); +} + +vec4 powRgba(vec4 _rgba, float _pow) +{ + vec4 result; + result.xyz = pow(_rgba.xyz, vec3_splat(_pow) ); + result.w = _rgba.w; + return result; +} + +vec3 calcLight(int _idx, vec3 _wpos, vec3 _normal, vec3 _view) +{ + vec3 lp = u_lightPosRadius[_idx].xyz - _wpos; + float attn = 1.0 - smoothstep(u_lightRgbInnerR[_idx].w, 1.0, length(lp) / u_lightPosRadius[_idx].w); + vec3 lightDir = normalize(lp); + vec2 bln = blinn(lightDir, _normal, _view); + vec4 lc = lit(bln.x, bln.y, 1.0); + vec3 rgb = u_lightRgbInnerR[_idx].xyz * saturate(lc.y) * attn; + return rgb; +} + +float toClipSpaceDepth(float _depthTextureZ) +{ +#if BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL + return _depthTextureZ; +#else + return _depthTextureZ * 2.0 - 1.0; +#endif // BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL +} + +vec3 clipToWorld(mat4 _invViewProj, vec3 _clipPos) +{ + vec4 wpos = mul(_invViewProj, vec4(_clipPos, 1.0) ); + return wpos.xyz / wpos.w; +} + +void main() +{ + vec3 normal = decodeNormalUint(texture2DArray(s_normal, vec3(v_texcoord0, 1.0) ).xyz); + float deviceDepth = texture2D(s_depth, v_texcoord0).x; + float depth = toClipSpaceDepth(deviceDepth); + + vec3 clip = vec3(v_texcoord0 * 2.0 - 1.0, depth); +#if BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL + clip.y = -clip.y; +#endif // BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL + vec3 wpos = clipToWorld(u_mtx, clip); + + vec3 view = mul(u_view, vec4(wpos, 0.0) ).xyz; + view = -normalize(view); + + vec3 lightColor; + lightColor = calcLight(0, wpos, normal, view); + gl_FragColor.xyz = toGamma(lightColor.xyz); + gl_FragColor.w = 1.0; +} diff --git a/examples/runtime/shaders/dx11/fs_deferred_light_ta.bin b/examples/runtime/shaders/dx11/fs_deferred_light_ta.bin new file mode 100644 index 000000000..fc51f3424 Binary files /dev/null and b/examples/runtime/shaders/dx11/fs_deferred_light_ta.bin differ diff --git a/examples/runtime/shaders/glsl/fs_deferred_light_ta.bin b/examples/runtime/shaders/glsl/fs_deferred_light_ta.bin new file mode 100644 index 000000000..d67f0098f Binary files /dev/null and b/examples/runtime/shaders/glsl/fs_deferred_light_ta.bin differ diff --git a/examples/runtime/shaders/metal/fs_deferred_light_ta.bin b/examples/runtime/shaders/metal/fs_deferred_light_ta.bin new file mode 100644 index 000000000..30b113de5 Binary files /dev/null and b/examples/runtime/shaders/metal/fs_deferred_light_ta.bin differ