Screen Space reflection bug


#1

Hey Bearish,
I am exploring your rendering engine features for my new application. Great work btw!
I noticed the screen space reflection was buggy and I was seeing artifacts. I have attached the pic of the artifact.


I set the quality of reflection to max 4, how do I get rid of this or is this a bug?

Another question I had was how do I set the color value of the roughness other than the default black, white and normal textures that are provided. Can’t I assign a color (any grey) to the roughness property of the the standard shader. I don’t see a way to assign color values to roughness or do I have to provide a texture?


#2

Could you upload your assets and code with the problematic scene? It could be a bug, or just a lack of precision.

The default standard shader only accepts roughness in the form of a texture.


#3

Thanks so much for your reply. I just modified the skeletal example to add a metallic floor and enabled screen space reflection. Also added rotation on the drone. The code is below. I see two problems:

  1. Reflection on the floor has lots of artifacts.
  2. If you get close to the drone model, you can see some swimming black textures. Hard to describe it but it’s like there is a lag in rendering once the ssr is turned on, where you see black pixel artifacts. I am using windows so I believe its using DX11 by default.
    Edit: I actually tried OpenGL and it has the same problem. Also I noticed this black pixel lag artifact that described above is present even without screen space reflection, ssr just makes it worse. Try to move the camera and notice the lag in drawing the reflection too.

Is there another PBR shader that allows to set color, roughness and metallic in float? This is limiting for me as I don’t want to have all the possible color values as textures in the system. Do I need to create a custom shader to make it accept colors and floats or just modify the standard shader to set colors?

Sorry couldn’t upload and attach as a file using editor because it only allows to upload images not source codes.

   // Framework includes
    #include "BsApplication.h"
    #include "Resources/BsResources.h"
    #include "Resources/BsBuiltinResources.h"
    #include "Material/BsMaterial.h"
    #include "Components/BsCCamera.h"
    #include "Components/BsCRenderable.h"
    #include "Components/BsCAnimation.h"
    #include "Components/BsCSkybox.h"
    #include "RenderAPI/BsRenderAPI.h"
    #include "RenderAPI/BsRenderWindow.h"
    #include "Scene/BsSceneObject.h"

    // Example includes
    #include "BsCameraFlyer.h"
    #include "BsExampleFramework.h"
    #include "BsObjectRotator.h"

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // This example demonstrates how to animate a 3D model using skeletal animation. Aside from animation this example is
    // structurally similar to PhysicallyBasedShading example.
    //
    // The example first loads necessary resources, including a mesh and textures to use for rendering, as well as an animation
    // clip. The animation clip is imported from the same file as the 3D model. Special import options are used to tell the
    // importer to import data required for skeletal animation. It then proceeds to register the relevant keys used for
    // controling the camera. Next it sets up the 3D scene using the mesh, textures, material and adds an animation
    // component. The animation component start playing the animation clip we imported earlier. Finally it sets up a camera,
    // along with CameraFlyer component that allows the user to fly around the scene.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    namespace bs
    {
    	UINT32 windowResWidth = 1280;
    	UINT32 windowResHeight = 720;

    	/** Container for all resources used by the example. */
    	struct Assets
    	{
    		HMesh exampleModel;
    		HAnimationClip exampleAnimClip;
    		HTexture exampleAlbedoTex;
    		HTexture exampleNormalsTex;
    		HTexture exampleRoughnessTex;
    		HTexture exampleMetalnessTex;
    		HTexture exampleSkyCubemap;
    		HMaterial exampleMaterial;
    	};

    	/** Load the resources we'll be using throughout the example. */
    	Assets loadAssets()
    	{
    		Assets assets;

    		// Load the 3D model and the animation clip

    		// Set up a path to the model resource
    		const Path exampleDataPath = EXAMPLE_DATA_PATH;
    		const Path modelPath = exampleDataPath + "MechDrone/Drone.FBX";

    		// Set up mesh import options so that we import information about the skeleton and the skin, as well as any
    		// animation clips the model might have.
    		SPtr<MeshImportOptions> meshImportOptions = MeshImportOptions::create();
    		meshImportOptions->setImportSkin(true);
    		meshImportOptions->setImportAnimation(true);

    		// The FBX file contains multiple resources (a mesh and an animation clip), therefore we use importAll() method,
    		// which imports all resources in a file.
    		Vector<SubResource> modelResources = gImporter().importAll(modelPath, meshImportOptions);
    		for(auto& entry : modelResources)
    		{
    			if(rtti_is_of_type<Mesh>(entry.value.get()))
    				assets.exampleModel = static_resource_cast<Mesh>(entry.value);
    			else if(rtti_is_of_type<AnimationClip>(entry.value.get()))
    				assets.exampleAnimClip = static_resource_cast<AnimationClip>(entry.value);
    		}

    		bs::HMesh floorMesh = gBuiltinResources().getMesh(BuiltinMesh::Quad);

    		HShader shader = gBuiltinResources().getBuiltinShader(BuiltinShader::Standard);
    		bs::HMaterial planeMat = Material::create(shader);
    		HTexture gridPattern2 = ExampleFramework::loadTexture(ExampleTexture::GridPattern2);
    		planeMat->setTexture("gAlbedoTex", gridPattern2);
    		//planeMat->setTexture("gAlbedoTex", BuiltinResources::getTexture(BuiltinTexture::White));
    		planeMat->setTexture("gMetalnessTex", BuiltinResources::getTexture(BuiltinTexture::White));
    		planeMat->setTexture("gRoughnessTex", BuiltinResources::getTexture(BuiltinTexture::Black));
    		planeMat->setVec2("gUVTile", Vector2::ONE * 50.0f * 0.5f);

    		HSceneObject floorSO = SceneObject::create("Floor");
    		floorSO->setPosition(Vector3(0.0f, -0.5f, 0.0f));

    		HRenderable floorRenderable = floorSO->addComponent<CRenderable>();
    		floorRenderable->setMesh(floorMesh);
    		floorRenderable->setMaterial(planeMat);
    		floorSO->setScale(Vector3(20.0f, 1.0f, 20.0f));a

    		// Load PBR textures for the 3D model
    		assets.exampleAlbedoTex = ExampleFramework::loadTexture(ExampleTexture::DroneAlbedo);
    		assets.exampleNormalsTex = ExampleFramework::loadTexture(ExampleTexture::DroneNormal, false);
    		assets.exampleRoughnessTex = ExampleFramework::loadTexture(ExampleTexture::DroneRoughness, false);
    		assets.exampleMetalnessTex = ExampleFramework::loadTexture(ExampleTexture::DroneMetalness, false);

    		// Create a material using the default physically based shader, and apply the PBR textures we just loaded
    		assets.exampleMaterial = Material::create(shader);

    		assets.exampleMaterial->setTexture("gAlbedoTex", assets.exampleAlbedoTex);
    		assets.exampleMaterial->setTexture("gNormalTex", assets.exampleNormalsTex);
    		assets.exampleMaterial->setTexture("gRoughnessTex", assets.exampleRoughnessTex);
    		assets.exampleMaterial->setTexture("gMetalnessTex", assets.exampleMetalnessTex);

    		// Load an environment map
    		assets.exampleSkyCubemap = ExampleFramework::loadTexture(ExampleTexture::EnvironmentDaytime, false, true, true);

    		return assets;
    	}

    	/** Set up the 3D object used by the example, and the camera to view the world through. */
    	void setUp3DScene(const Assets& assets)
    	{
    		/************************************************************************/
    		/* 									RENDERABLE                  		*/
    		/************************************************************************/

    		// Now we create a scene object that has a position, orientation, scale and optionally components to govern its 
    		// logic. In this particular case we are creating a SceneObject with a Renderable component which will render a
    		// mesh at the position of the scene object with the provided material.

    		// Create new scene object at (0, 0, 0)
    		HSceneObject droneSO = SceneObject::create("Drone");
    		
    		// Attach the Renderable component and hook up the mesh we loaded, and the material we created.
    		HRenderable renderable = droneSO->addComponent<CRenderable>();
    		renderable->setMesh(assets.exampleModel);
    		renderable->setMaterial(assets.exampleMaterial);

    		droneSO->addComponent<ObjectRotator>();

    		/************************************************************************/
    		/* 									ANIMATION	                  		*/
    		/************************************************************************/

    		// Add an animation component to the same scene object we added Renderable to.
    		HAnimation animation = droneSO->addComponent<CAnimation>();

    		// Start playing the animation clip we imported
    		animation->play(assets.exampleAnimClip);

    		/************************************************************************/
    		/* 									SKYBOX                       		*/
    		/************************************************************************/

    		// Add a skybox texture for sky reflections
    		HSceneObject skyboxSO = SceneObject::create("Skybox");

    		HSkybox skybox = skyboxSO->addComponent<CSkybox>();
    		skybox->setTexture(assets.exampleSkyCubemap);

    		/************************************************************************/
    		/* 									CAMERA	                     		*/
    		/************************************************************************/

    		// In order something to render on screen we need at least one camera.

    		// Like before, we create a new scene object at (0, 0, 0).
    		HSceneObject sceneCameraSO = SceneObject::create("SceneCamera");

    		// Get the primary render window we need for creating the camera. 
    		SPtr<RenderWindow> window = gApplication().getPrimaryWindow();

    		// Add a Camera component that will output whatever it sees into that window 
    		// (You could also use a render texture or another window you created).
    		HCamera sceneCamera = sceneCameraSO->addComponent<CCamera>();
    		sceneCamera->getViewport()->setTarget(window);

    		// Set up camera component properties

    		// Set closest distance that is visible. Anything below that is clipped.
    		sceneCamera->setNearClipDistance(0.005f);

    		// Set farthest distance that is visible. Anything above that is clipped.
    		sceneCamera->setFarClipDistance(1000);

    		// Set aspect ratio depending on the current resolution
    		sceneCamera->setAspectRatio(windowResWidth / (float)windowResHeight);

    		// Enable multi-sample anti-aliasing for better quality
    		sceneCamera->setMSAACount(4);

    		// Enable indirect lighting so we get accurate diffuse lighting from the skybox environment map
    		const SPtr<RenderSettings>& renderSettings = sceneCamera->getRenderSettings();
    		renderSettings->enableIndirectLighting = true;
    		renderSettings->screenSpaceReflections.enabled = true;
    		renderSettings->screenSpaceReflections.maxRoughness = 0.8f;
    		renderSettings->screenSpaceReflections.quality = 4;

    		sceneCamera->setRenderSettings(renderSettings);

    		// Add a CameraFlyer component that allows us to move the camera. See CameraFlyer for more information.
    		sceneCameraSO->addComponent<CameraFlyer>();

    		// Position and orient the camera scene object
    		sceneCameraSO->setPosition(Vector3(0.0f, 2.5f, -4.0f) * 0.65f);
    		sceneCameraSO->lookAt(Vector3(0, 1.5f, 0));
    	}
    }

    /** Main entry point into the application. */
    #if BS_PLATFORM == BS_PLATFORM_WIN32
    #include <windows.h>

    int CALLBACK WinMain(
    	_In_  HINSTANCE hInstance,
    	_In_  HINSTANCE hPrevInstance,
    	_In_  LPSTR lpCmdLine,
    	_In_  int nCmdShow
    	)
    #else
    int main()
    #endif
    {
    	using namespace bs;

    	// Initializes the application and creates a window with the specified properties
    	VideoMode videoMode(windowResWidth, windowResHeight);
    	Application::startUp(videoMode, "Example", false);

    	// Registers a default set of input controls
    	ExampleFramework::setupInputConfig();

    	// Load a model and textures, create materials
    	Assets assets = loadAssets();

    	// Set up the scene with an object to render and a camera
    	setUp3DScene(assets);
    	
    	// Runs the main loop that does most of the work. This method will exit when user closes the main
    	// window or exits in some other way.
    	Application::instance().runMainLoop();

    	// When done, clean up
    	Application::shutDown();

    	return 0;
    }

#4

Thanks, I’ll add the issue to my backlog and investigate when I get a moment.

You need to make a custom shader if you want different parameters. Use Data\Raw\Shaders\Diffuse.bsl as a base.


#5

Thank you ! Could you please add the link to the bug here once you create it so I can track it?

Another thing I noticed is dx11 crashes above 8 msaa. When I set it to 16 msaa app crashes on my gtx 1080 t1 graphics card. Which is not a big problem for me as I plan to use opengl. In opengl version I can set it to 16 or even 32 and the app runs fine, but the scene becomes noticeably darker as I increase the msaa above 8 and even increasing the skybox brightness or adding bring light doesn’t help. It just looks like a washed out grey image.


#6

Please submit the bug reports here if you want them tracked: https://github.com/GameFoundry/bsf/issues . Otherwise I just keep them internally.

Only MSAA up to 8x is supported by the default shaders. Anything higher is undefined behavior.