Coder Social home page Coder Social logo

matt77hias / mage-v0 Goto Github PK

View Code? Open in Web Editor NEW
259.0 11.0 20.0 10.65 MB

๐Ÿง™ MAGE v0

Home Page: https://matt77hias.github.io/MAGE-v0-Doc

License: GNU General Public License v3.0

C++ 82.70% HLSL 17.30%
game-engine directx directx-11 direct3d d3d11 mage

mage-v0's Introduction

Build status Code quality Documentation License

MAGE v0

About

Game and rendering engine featuring both forward and deferred PBR (physically-based rendering) pipelines with optional indirect illumination using Voxel Cone Tracing.

Index

Development

  • Platform: Windows 10 32 Bit and 64 Bit (Windows API + Direct3D 11)
  • Engine Programming Language: C++17
  • Scripting Language: C++17
  • Shading Language: HLSL (Shader Model 5.0)

Copyright ยฉ 2016-2024 Matthias Moulin. All Rights Reserved.

mage-v0's People

Contributors

matt77hias avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mage-v0's Issues

C++17

Integrate

  • std::variant

  • std::filesystem

  • std::from_chars

  • double check noexcept for default method definitions.

  • Make the return value of BufferLock mage::PrimitiveBatchMesh::Lock const when "guaranteed copy elision" is added to MVSC++.

IDXGIAdapter selection

Currently the IDXGIAdapter with the most dedicated DedicatedVideoMemory is chosen and cannot be changed by the user in for example the graphics settings dialog window. This can result in a crash if no IDXGIOutput is associated with that IDXGIAdapter.

Easy fix: select the IDXGIAdapter with the most DedicatedVideoMemory and at least one IDXGIOutput.
Less easy fix due to the low level dialog system: let the user decide.

Note that notebooks with a dedicated GPU and integrated GPU are handled correctly in the current implementation in favor of the dedicated GPU although no IDXGIOutput is actually associated with the corresponding IDXGIAdapter.

noexcept move constructor

Apparently some std classes still do not have noexcept move constructors in C++17. If this changes in the future, code can be reduced by making some move constructors explicitly default:

  • std::exception (exception.hpp)
  • std::function (memory.hpp)
  • std::unordered_multimap (node.hpp)
  • std::map (resource_pool.hpp, resource_manager.hpp)

DeviceEnumeration Enhancements

  • Let the user chose the IDXGIAdapter2 and IDXGIOutput2.

  • Use the selected IDXGIOutput2 of DeviceEnumeration in Renderer.

  • Use the selected vsync and refresh rate options in Renderer (in the presence of mode switching).

Rebuilt with AppVeyor

If AppVeyor finally updates to VS 2017 15.5, all recent builds need to be redone.

BehaviorScript and Scene

BehaviorScript and Scene should be loaded and closed with the load and close function instead of using the constructor and destructor.

Still, full destruction must however still be guarenteed.

Scenes must now also be switched from within a BehaviorScript which directly calls the Engine. Probably, a new SceneManager could fill this gap via an indirection.

Repository size: images

To reduce the repository size even further, all images should be moved to the meta repository and the git history should be updated.

glTF2 standard order

The RMA texture uses the glTF2 standard order: The metalness is in the B channel, roughness in the G channel, and ambient occlusion in the R channel. If there's no ambient occlusion, then the R channel should be set to all 1.

AO should be added. R and M should be shifted and re-compressed.

Maybe Material should be called ARM?

Connection between DeviceEnumeration and Renderer

The DeviceEnumeration provides the IDXGIAdapter2 and the corresponding IDXGIOutput2. Currently the Renderer does not use this IDXGIAdapter2 in D3D11CreateDevice but instead uses nullptr. Using this IDXGIAdapter2 results in a 0x887a0004 failure.

Note that D3D_DRIVER_TYPE_UNKNOWN if pAdapter != nullptr.

Artifacts in omni light shadow mapping

Spotlight

My spotlight's intensity is cut off at a distance of 3 and at an angle of $\pi/4$ radians (umbra angle). The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. The spotlight is positioned somewhere above the tree and faces downward to the floor.

The shadow map of my spotlight has a resolution of 512x512. I use the following DXGI formats:

  • DXGI_FORMAT_R16_TYPELESS: texture resource;
  • DXGI_FORMAT_D16_UNORM: DSV (one for each spotlight);
  • DXGI_FORMAT_R16_UNORM: SRV (one Texture2DArray for all, spotlights).

My shadow factor is calculated in HLSL as:

/**
 Calculates the shadow factor.

 @pre			@a shadow_maps must contain a shadow map at index @a index.
 @param[in]		pcf_sampler
				The PCF sampler comparison state.
 @param[in]		shadow_maps
				The array of shadow maps.
 @param[in]		index
				The index into the array of shadow maps.
 @param[in]		p_proj
				The hit position in light projection space coordinates.
 */
float ShadowFactor(SamplerComparisonState pcf_sampler,
	Texture2DArray< float > shadow_maps, uint index,
	float4 p_proj) {

	const float  inv_w  = 1.0f / p_proj.w;
	const float3 p_ndc  = p_proj.xyz * inv_w;
	const float3 loc    = float3(NDCtoUV(p_ndc.xy), index);
	
	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc.z);
}

Here, the hit position in light projection space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):

const float4 p_proj = mul(float4(p, 1.0f), light.cview_to_lprojection);

I obtain the following images after visualizing the shadow factor (this is not the light contribution of the spotlight) (and some linear fog as well):

enter image description here
enter image description here

This seems to result in the correct behavior (see the shadows of the leaves, pillars and curtains). The bright border on the first image starts at the position of the spotlight and is due to the near plane distance of 0.1. This border will completely vanish after multiplying the shadow factor with the spotlight's contribution.

Omni light

My omni light's intensity is cut off at a distance of 3. The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. This means that one of the six light cameras (after applying some rotations), is completely identical to the spotlight camera above. I double checked this in the code:

Frame 1:
world_to_lprojection (spotlight):

1.16532457,  0.000000000, 0.000000000, 0.000000000
0.000000000, -2.18211127e-07, -1.03448260, -0.999999881
0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07
0.000000000, 4.36422255e-07, 1.96551692, 1.99999976

world_to_lprojection (fourth omni light camera):

1.16532457, 0.000000000, 0.000000000, 0.000000000
0.000000000, -2.18211127e-07, -1.03448260, -0.999999881
0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07
0.000000000, 4.36422255e-07, 1.96551692, 1.99999976

world_to_lprojection represents the world-to-light-projection transformation matrix (world-to-camera-view-to-world-to-light-view-to-light-projection). I go to camera view first to mimic the same multiplications between my depth passes and shading passes to reduce z-fighting (although, this does not result in visual differences so far).

So apart from the fact that a spotlight corresponds to one DSV (and is part of one SRV to a Texture2DArray for all spotlight shadow maps) and an omni light corresponds to six DSVs (and is part of one SRV to a Texture2DCubeArray for all omni light shadow cube maps), the shadow map generation is pretty much the same for both types of lights.

The shadow map of my omni light has a resolution of 512x512. I use the following DXGI formats:

  • DXGI_FORMAT_R16_TYPELESS: texture resource;
  • DXGI_FORMAT_D16_UNORM: DSV (one for each omni light);
  • DXGI_FORMAT_R16_UNORM: SRV (one Texture2DCubeArray for all, omni lights).

My shadow factor is calculated in HLSL as:

/**
 Calculates the shadow factor.

 @pre			@a shadow_maps must contain a shadow cube map at index @a index.
 @param[in]		pcf_sampler
				The PCF sampler comparison state.
 @param[in]		shadow_maps
				The array of shadow cube maps.
 @param[in]		index
				The index into the array of shadow cube maps.
 @param[in]		p_view
				The hit position in light view space coordinates.
 @param[in]		projection_values
				The projection values [view_projection22, view_projection32].
 */
float ShadowFactor(SamplerComparisonState pcf_sampler, 
	TextureCubeArray< float > shadow_maps, uint index,
	float3 p_view, float2 projection_values) {

	const float p_view_z = Max(abs(p_view));
	const float p_ndc_z  = ViewZtoNDCZ(p_view_z, projection_values);
	const float4 loc     = float4(p_view, index);

	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc_z);
}

Here, the hit position in light view space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):

const float3 p_view = mul(float4(p, 1.0f), light.cview_to_lview).xyz;

The conversion of the z coordinate to NDC space is done as follows:

/**
 Converts the given (linear) view z-coordinate to the (non-linear) NDC 
 z-coordinate.

 @param[in]     p_view_z
                The (linear) view z-coordinate.
 @param[in]     projection_values
                The projection values [view_projection22, view_projection32].
 @return        The (non-linear) NDC z-coordinate.
 */
float ViewZtoNDCZ(float p_view_z, float2 projection_values) {
    return projection_values.x + projection_values.y / p_view_z;
}

with the following dual C++ method:

/**
 Returns the projection values from the given projection matrix to construct 
 the NDC position z-coordinate from the view position z-coordinate.

 @return        The projection values from the given projection matrix to 
                construct the NDC position z-coordinate from the view position 
                z-coordinate.
 */
inline const XMVECTOR XM_CALLCONV GetNDCZConstructionValues(
    FXMMATRIX projection_matrix) noexcept {

    //        [ _  0  0  0 ]
    // p_view [ 0  _  0  0 ] = [_, _, p_view.z * X + Y, p_view.z] = p_proj
    //        [ 0  0  X  1 ]
    //        [ 0  0  Y  0 ]
    //
    // p_proj / p_proj.w     = [_, _, X + Y/p_view.z, 1] = p_ndc
    //
    // Construction of p_ndc.z from p_view and projection values
    // p_ndc.z = X + Y/p_view.z

    const F32 x = XMVectorGetZ(projection_matrix.r[2]);
    const F32 y = XMVectorGetZ(projection_matrix.r[3]);
    
    return XMVectorSet(x, y, 0.0f, 0.0f);
}

I obtain the following images after visualizing the shadow factor (this is not the light contribution of the omni light) (and some linear fog as well):

enter image description here
enter image description here

This is clearly wrong. All six shadow maps seem kind of stretched. Without the stretching, the curtain's shadow would still be in the close vicinity of the curtain itself and the leaves' shadow would be much smaller (equal to the leaves' shadow for the spotlight). Furthermore, the circular shadow at the end of the pillar's shadow is associated to the buckets in front of the curtains.

Any ideas what goes or could go wrong?

For clarity, the following two images show the shadow factor of the cube map face corresponding to the spotlight, for the omni light by adding:

if (p_view_z != -p_view.y) {
	return 0.0f;
}

enter image description here
enter image description here

The lit area seems a bit (how much?) larger than for the spotlight.

SampleCmpLevelZero

An other strange observation is that using a depth value of 1.1 for my spotlight's PCF filtering (SampleCmpLevelZero) always results in a 0 value as expected:

enter image description here

whereas for my omni light this is not the case:

enter image description here

Even if I use a value equal to 100000.0, I'll notice lit areas?

Depth Biasing

I use DepthBias = 100; (to prevent shadow acne; note that I use 16bit depth maps) SlopeScaledDepthBias = 0.0f; DepthBiasClamp = 0.0f; for all my Rasterizer states.

PCF filtering

I use the following sampler comparison state for PCF filtering (my shadow maps have no mipmaps) for both spotlights and omni lights.

D3D11_SAMPLER_DESC desc = {};
desc.Filter         = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
desc.AddressU       = D3D11_TEXTURE_ADDRESS_BORDER;
desc.AddressV       = D3D11_TEXTURE_ADDRESS_BORDER;
desc.AddressW       = D3D11_TEXTURE_ADDRESS_BORDER;
desc.MaxAnisotropy  = (device->GetFeatureLevel() > D3D_FEATURE_LEVEL_9_1) 
								? D3D11_MAX_MAXANISOTROPY : 2;
desc.MaxLOD         = D3D11_FLOAT32_MAX;
desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;

Possible optimization reminders

  • non-linear material coefficient compression for deferred shading
  • early-depth pass for large models only
  • partial culling of shadow maps for omni lights
  • proper handling of MSAA and deferred shading (e.g. inferred lighting)
  • proper handling of orthographic cameras and deferred shading

x86 C++17 alignas

Double check C++17 alignas (instead of C++11) for heap allocation in x86 versions when Visual Studio 2017 15.5 is available

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.