Page 1 of 1

[Solved] Detail normal 'value' issue

Posted: Wed Aug 14, 2019 2:57 pm
by hedphelym
Hi,
we're having some issues with some of the shaders, it seems that the 'value' in the json only affects the "detail_normal0".
If we then add the same as 'detail_normal1' then the value of the normals are not affected (basically '1'), regardless of what we put in 'value' in the material file.

Two examples:

This works - and 'value' can be altered, the normals works as expected.

Code: Select all

"detail_normal0" : 
{
			   "uv" : -1,
			   "offset" : [0.0,0.0],
			   "scale" : [0.1,0.1],
			   "value" : 0.1,
			   "texture" : "normal.png", 
			   "sampler" : "undefined"
},

With this one - the 'value' has no effect, if it's set to '0' then it still shows as full value on the normals in the map.

Code: Select all

"detail_normal1" : 
{
			   "uv" : -1,
			   "offset" : [0.0,0.0],
			   "scale" : [0.1,0.1],
			   "value" : 0.1,
			   "texture" : "normal.png", 
			   "sampler" : "undefined"
},
I cannot immediately see that there is something wrong with the json parse code itself, so I'm wondering where the problem lies.
Has anyone of you seen the same problem?

Re: Detail normal 'value' issue

Posted: Thu Aug 15, 2019 1:40 am
by dark_sylinc
I suspect the reason could be that setProperty( *PbsProperty::DetailNormalWeights[validDetailMaps], 1 ); is not being set properly.

Do you have a dump of the generated shaders in charge of rendering that object? (with dumped properties, ensure Hlms::mDebugOutputProperties is true)

Edit: I may be misunderstanding the problem. Could you post a modified example with the problem and a few pics?

Re: Detail normal 'value' issue

Posted: Thu Aug 15, 2019 8:23 am
by hedphelym
I do not have time for the output of the shaders today (busy day at the office with meetings etc), but I can look into that tonight or tomorrow morning.
It seems like the index is wrong (like you are saying).

If I add a normal map in both 'detail_normal0' and 'detail_normal1' and set both to 'value : 0' - the bump is not showing (as expected).
If I then unplug the one in 'detail_normal0' and leave the 'detail_normal1' as previously (with value 0) it then shows 'detail_normal1's map as if it's with value '1' in the generated shader.

So it seems the index is '0' for 'detail_normal1' when only 'detail_normal1' is assigned to the material, and not index '1'.

Hope this explains it better, let me know if you need more info.

Re: Detail normal 'value' issue

Posted: Thu Aug 15, 2019 4:26 pm
by dark_sylinc
Hi!

Because I'm usually busy, it would help me a ton if there's just a snippet of code I can copy paste into one of the samples so I can repro the problem quickly.
Having extra files is also OK.

Even if it'd be is easy for me to repro, all the time I can save helps!

Re: Detail normal 'value' issue

Posted: Thu Aug 15, 2019 4:53 pm
by hedphelym
I completely understand. I will see If I can make that tonight.

Re: Detail normal 'value' issue

Posted: Thu Aug 15, 2019 9:04 pm
by hedphelym
I was able to reproduce the issue now in code.
Took some time to get everything up and running tonight, but now I have a easy example for you to test with.

As you can see in my screenshot - the red spheres have detail normal mapping applied,
even thought the 'setDetailNormalWeight' is set to zero (PBSM_DETAIL1_NM).

The green spheres has a map set in PBSM_DETAIL0_NM, and also has 'setDetailNormalWeight' set to '0' - they appear as expected.

Image

Place this code in 'PbsMaterialsGameState.cpp' sample project, compile and run:
(Line 151 to 170 is where my changes are located.

Code: Select all


#include "PbsMaterialsGameState.h"
#include "CameraController.h"
#include "GraphicsSystem.h"

#include "OgreSceneManager.h"
#include "OgreItem.h"

#include "OgreMeshManager.h"
#include "OgreMeshManager2.h"
#include "OgreMesh2.h"

#include "OgreCamera.h"
#include "OgreRenderWindow.h"

#include "OgreHlmsPbsDatablock.h"
#include "OgreHlmsSamplerblock.h"

#include "OgreRoot.h"
#include "OgreHlmsManager.h"
#include "OgreHlmsTextureManager.h"
#include "OgreHlmsPbs.h"

using namespace Demo;

namespace Demo
{
    PbsMaterialsGameState::PbsMaterialsGameState( const Ogre::String &helpDescription ) :
        TutorialGameState( helpDescription ),
        mAnimateObjects( true ),
        mNumSpheres( 0 ),
        mTransparencyMode( Ogre::HlmsPbsDatablock::None ),
        mTransparencyValue( 1.0f )
    {
        memset( mSceneNode, 0, sizeof(mSceneNode) );
    }
    //-----------------------------------------------------------------------------------
    void PbsMaterialsGameState::createScene01(void)
    {
        Ogre::SceneManager *sceneManager = mGraphicsSystem->getSceneManager();

        const float armsLength = 2.5f;

        Ogre::v1::MeshPtr planeMeshV1 = Ogre::v1::MeshManager::getSingleton().createPlane( "Plane v1",
                                            Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
                                            Ogre::Plane( Ogre::Vector3::UNIT_Y, 1.0f ), 50.0f, 50.0f,
                                            1, 1, true, 1, 4.0f, 4.0f, Ogre::Vector3::UNIT_Z,
                                            Ogre::v1::HardwareBuffer::HBU_STATIC,
                                            Ogre::v1::HardwareBuffer::HBU_STATIC );

        Ogre::MeshPtr planeMesh = Ogre::MeshManager::getSingleton().createManual(
                    "Plane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );

        planeMesh->importV1( planeMeshV1.get(), true, true, true );

        {
            Ogre::Item *item = sceneManager->createItem( planeMesh, Ogre::SCENE_DYNAMIC );
            item->setDatablock( "Marble" );
            Ogre::SceneNode *sceneNode = sceneManager->getRootSceneNode( Ogre::SCENE_DYNAMIC )->
                                                    createChildSceneNode( Ogre::SCENE_DYNAMIC );
            sceneNode->setPosition( 0, -1, 0 );
            sceneNode->attachObject( item );

            //Change the addressing mode of the roughness map to wrap via code.
            //Detail maps default to wrap, but the rest to clamp.
            assert( dynamic_cast<Ogre::HlmsPbsDatablock*>( item->getSubItem(0)->getDatablock() ) );
            Ogre::HlmsPbsDatablock *datablock = static_cast<Ogre::HlmsPbsDatablock*>(
                                                            item->getSubItem(0)->getDatablock() );
            //Make a hard copy of the sampler block
            Ogre::HlmsSamplerblock samplerblock( *datablock->getSamplerblock( Ogre::PBSM_ROUGHNESS ) );
            samplerblock.mU = Ogre::TAM_WRAP;
            samplerblock.mV = Ogre::TAM_WRAP;
            samplerblock.mW = Ogre::TAM_WRAP;
            //Set the new samplerblock. The Hlms system will
            //automatically create the API block if necessary
            datablock->setSamplerblock( Ogre::PBSM_ROUGHNESS, samplerblock );
        }

        for( int i=0; i<4; ++i )
        {
            for( int j=0; j<4; ++j )
            {
                Ogre::String meshName;

                if( i == j )
                    meshName = "Sphere1000.mesh";
                else
                    meshName = "Cube_d.mesh";

                Ogre::Item *item = sceneManager->createItem( meshName,
                                                             Ogre::ResourceGroupManager::
                                                             AUTODETECT_RESOURCE_GROUP_NAME,
                                                             Ogre::SCENE_DYNAMIC );
                if( i % 2 == 0 )
                    item->setDatablock( "Rocks" );
                else
                    item->setDatablock( "Marble" );

                item->setVisibilityFlags( 0x000000001 );

                size_t idx = i * 4 + j;

                mSceneNode[idx] = sceneManager->getRootSceneNode( Ogre::SCENE_DYNAMIC )->
                        createChildSceneNode( Ogre::SCENE_DYNAMIC );

                mSceneNode[idx]->setPosition( (i - 1.5f) * armsLength,
                                              2.0f,
                                              (j - 1.5f) * armsLength );
                mSceneNode[idx]->setScale( 0.65f, 0.65f, 0.65f );

                mSceneNode[idx]->roll( Ogre::Radian( (Ogre::Real)idx ) );

                mSceneNode[idx]->attachObject( item );
            }
        }

		{
			mNumSpheres = 0;
			Ogre::HlmsManager *hlmsManager = mGraphicsSystem->getRoot()->getHlmsManager();
			Ogre::HlmsTextureManager *hlmsTextureManager = hlmsManager->getTextureManager();

			assert(dynamic_cast<Ogre::HlmsPbs*>(hlmsManager->getHlms(Ogre::HLMS_PBS)));

			Ogre::HlmsPbs *hlmsPbs = static_cast<Ogre::HlmsPbs*>(hlmsManager->getHlms(Ogre::HLMS_PBS));

			const int numX = 8;
			const int numZ = 8;

			const float armsLength = 1.0f;
			const float startX = (numX - 1) / 2.0f;
			const float startZ = (numZ - 1) / 2.0f;


			for (int x = 0; x < numX; ++x)
			{

				for (int z = 0; z < numZ; ++z)
				{
					Ogre::String datablockName = "Test" + Ogre::StringConverter::toString(mNumSpheres++);
					Ogre::HlmsPbsDatablock *datablock = static_cast<Ogre::HlmsPbsDatablock*>(
						hlmsPbs->createDatablock(datablockName,
							datablockName,
							Ogre::HlmsMacroblock(),
							Ogre::HlmsBlendblock(),
							Ogre::HlmsParamVec()));

					Ogre::HlmsTextureManager::TextureLocation texLocation = hlmsTextureManager->
						createOrRetrieveTexture("SaintPetersBasilica.dds",
							Ogre::HlmsTextureManager::TEXTURE_TYPE_ENV_MAP);

					Ogre::HlmsTextureManager::TextureLocation texNormal = hlmsTextureManager->
						createOrRetrieveTexture("MRAMOR-bump.jpg",
							Ogre::HlmsTextureManager::TEXTURE_TYPE_DETAIL_NORMAL_MAP);

					datablock->setTexture(Ogre::PBSM_REFLECTION, texLocation.xIdx, texLocation.texture);



					if (x % 2 == 0)
					{
						datablock->setDiffuse(Ogre::Vector3(0.0f, 1.0f, 0.0f));
						datablock->setTexture(Ogre::PBSM_DETAIL0_NM, texNormal.xIdx, texNormal.texture);
						datablock->setDetailNormalWeight(texNormal.xIdx, 0);
					}
					else
					{
						datablock->setDiffuse(Ogre::Vector3(1.0f, 0.0f, 0.0f));
						datablock->setTexture(Ogre::PBSM_DETAIL1_NM, texNormal.xIdx, texNormal.texture);
						datablock->setDetailNormalWeight(texNormal.xIdx, 0);
					}



					datablock->setRoughness(std::max(0.02f, x / Ogre::max(1, (float)(numX - 1))));
					datablock->setFresnel(Ogre::Vector3(z / Ogre::max(1, (float)(numZ - 1))), false);

					Ogre::Item *item = sceneManager->createItem("Sphere1000.mesh",
						Ogre::ResourceGroupManager::
						AUTODETECT_RESOURCE_GROUP_NAME,
						Ogre::SCENE_DYNAMIC);
					item->setDatablock(datablock);
					item->setVisibilityFlags(0x000000002);

					Ogre::SceneNode *sceneNode = sceneManager->getRootSceneNode(Ogre::SCENE_DYNAMIC)->
						createChildSceneNode(Ogre::SCENE_DYNAMIC);
					sceneNode->setPosition(Ogre::Vector3(armsLength * x - startX,
						1.0f,
						armsLength * z - startZ));
					sceneNode->attachObject(item);
				}
			}
		}

        Ogre::SceneNode *rootNode = sceneManager->getRootSceneNode();

        Ogre::Light *light = sceneManager->createLight();
        Ogre::SceneNode *lightNode = rootNode->createChildSceneNode();
        lightNode->attachObject( light );
        light->setPowerScale( 1.0f );
        light->setType( Ogre::Light::LT_DIRECTIONAL );
        light->setDirection( Ogre::Vector3( -1, -1, -1 ).normalisedCopy() );

        mLightNodes[0] = lightNode;

        sceneManager->setAmbientLight( Ogre::ColourValue( 0.3f, 0.5f, 0.7f ) * 0.1f * 0.75f,
                                       Ogre::ColourValue( 0.6f, 0.45f, 0.3f ) * 0.065f * 0.75f,
                                       -light->getDirection() + Ogre::Vector3::UNIT_Y * 0.2f );

        light = sceneManager->createLight();
        lightNode = rootNode->createChildSceneNode();
        lightNode->attachObject( light );
        light->setDiffuseColour( 0.8f, 0.4f, 0.2f ); //Warm
        light->setSpecularColour( 0.8f, 0.4f, 0.2f );
        light->setPowerScale( Ogre::Math::PI );
        light->setType( Ogre::Light::LT_SPOTLIGHT );
        lightNode->setPosition( -10.0f, 10.0f, 10.0f );
        light->setDirection( Ogre::Vector3( 1, -1, -1 ).normalisedCopy() );
        light->setAttenuationBasedOnRadius( 10.0f, 0.01f );

        mLightNodes[1] = lightNode;

        light = sceneManager->createLight();
        lightNode = rootNode->createChildSceneNode();
        lightNode->attachObject( light );
        light->setDiffuseColour( 0.2f, 0.4f, 0.8f ); //Cold
        light->setSpecularColour( 0.2f, 0.4f, 0.8f );
        light->setPowerScale( Ogre::Math::PI );
        light->setType( Ogre::Light::LT_SPOTLIGHT );
        lightNode->setPosition( 10.0f, 10.0f, -10.0f );
        light->setDirection( Ogre::Vector3( -1, -1, 1 ).normalisedCopy() );
        light->setAttenuationBasedOnRadius( 10.0f, 0.01f );

        mLightNodes[2] = lightNode;

        mCameraController = new CameraController( mGraphicsSystem, false );

        TutorialGameState::createScene01();
    }
    //-----------------------------------------------------------------------------------
    void PbsMaterialsGameState::update( float timeSinceLast )
    {
        if( mAnimateObjects )
        {
            for( int i=0; i<16; ++i )
                mSceneNode[i]->yaw( Ogre::Radian(timeSinceLast * i * 0.125f) );
        }

        TutorialGameState::update( timeSinceLast );
    }
    //-----------------------------------------------------------------------------------
    void PbsMaterialsGameState::generateDebugText( float timeSinceLast, Ogre::String &outText )
    {
        Ogre::uint32 visibilityMask = mGraphicsSystem->getSceneManager()->getVisibilityMask();

        TutorialGameState::generateDebugText( timeSinceLast, outText );
        outText += "\nPress F2 to toggle animation. ";
        outText += mAnimateObjects ? "[On]" : "[Off]";
        outText += "\nPress F3 to show/hide animated objects. ";
        outText += (visibilityMask & 0x000000001) ? "[On]" : "[Off]";
        outText += "\nPress F4 to show/hide palette of spheres. ";
        outText += (visibilityMask & 0x000000002) ? "[On]" : "[Off]";
        outText += "\nPress F5 to toggle transparency mode. ";
        outText += mTransparencyMode == Ogre::HlmsPbsDatablock::Fade ? "[Fade]" : "[Transparent]";
        outText += "\n+/- to change transparency. [";
        outText += Ogre::StringConverter::toString( mTransparencyValue ) + "]";
    }
    //-----------------------------------------------------------------------------------
    void PbsMaterialsGameState::setTransparencyToMaterials(void)
    {
        Ogre::HlmsManager *hlmsManager = mGraphicsSystem->getRoot()->getHlmsManager();

        assert( dynamic_cast<Ogre::HlmsPbs*>( hlmsManager->getHlms( Ogre::HLMS_PBS ) ) );

        Ogre::HlmsPbs *hlmsPbs = static_cast<Ogre::HlmsPbs*>( hlmsManager->getHlms(Ogre::HLMS_PBS) );

        Ogre::HlmsPbsDatablock::TransparencyModes mode =
                static_cast<Ogre::HlmsPbsDatablock::TransparencyModes>( mTransparencyMode );

        if( mTransparencyValue >= 1.0f )
            mode = Ogre::HlmsPbsDatablock::None;

        if( mTransparencyMode < 1.0f && mode == Ogre::HlmsPbsDatablock::None )
            mode = Ogre::HlmsPbsDatablock::Transparent;

        for( size_t i=0; i<mNumSpheres; ++i )
        {
            Ogre::String datablockName = "Test" + Ogre::StringConverter::toString( i );
            Ogre::HlmsPbsDatablock *datablock = static_cast<Ogre::HlmsPbsDatablock*>(
                        hlmsPbs->getDatablock( datablockName ) );

            datablock->setTransparency( mTransparencyValue, mode );
        }
    }
    //-----------------------------------------------------------------------------------
    void PbsMaterialsGameState::keyReleased( const SDL_KeyboardEvent &arg )
    {
        if( (arg.keysym.mod & ~(KMOD_NUM|KMOD_CAPS)) != 0 )
        {
            TutorialGameState::keyReleased( arg );
            return;
        }

        if( arg.keysym.sym == SDLK_F2 )
        {
            mAnimateObjects = !mAnimateObjects;
        }
        else if( arg.keysym.sym == SDLK_F3 )
        {
            Ogre::uint32 visibilityMask = mGraphicsSystem->getSceneManager()->getVisibilityMask();
            bool showMovingObjects = (visibilityMask & 0x00000001);
            showMovingObjects = !showMovingObjects;
            visibilityMask &= ~0x00000001;
            visibilityMask |= (Ogre::uint32)showMovingObjects;
            mGraphicsSystem->getSceneManager()->setVisibilityMask( visibilityMask );
        }
        else if( arg.keysym.sym == SDLK_F4 )
        {
            Ogre::uint32 visibilityMask = mGraphicsSystem->getSceneManager()->getVisibilityMask();
            bool showPalette = (visibilityMask & 0x00000002) != 0;
            showPalette = !showPalette;
            visibilityMask &= ~0x00000002;
            visibilityMask |= (Ogre::uint32)(showPalette) << 1;
            mGraphicsSystem->getSceneManager()->setVisibilityMask( visibilityMask );
        }
        else if( arg.keysym.sym == SDLK_F5 )
        {
            mTransparencyMode = mTransparencyMode == Ogre::HlmsPbsDatablock::Fade ?
                                                            Ogre::HlmsPbsDatablock::Transparent :
                                                            Ogre::HlmsPbsDatablock::Fade;
            if( mTransparencyValue != 1.0f )
                setTransparencyToMaterials();
        }
        else if( arg.keysym.scancode == SDL_SCANCODE_KP_PLUS )
        {
            if( mTransparencyValue < 1.0f )
            {
                mTransparencyValue += 0.1f;
                mTransparencyValue = Ogre::min( mTransparencyValue, 1.0f );
                setTransparencyToMaterials();
            }
        }
        else if( arg.keysym.scancode == SDL_SCANCODE_MINUS ||
                 arg.keysym.scancode == SDL_SCANCODE_KP_MINUS )
        {
            if( mTransparencyValue > 0.0f )
            {
                mTransparencyValue -= 0.1f;
                mTransparencyValue = Ogre::max( mTransparencyValue, 0.0f );
                setTransparencyToMaterials();
            }
        }
        else
        {
            TutorialGameState::keyReleased( arg );
        }
    }
}

Re: Detail normal 'value' issue

Posted: Thu Aug 15, 2019 11:40 pm
by dark_sylinc
Fixed. Thanks for the report!

Re: Detail normal 'value' issue

Posted: Fri Aug 16, 2019 5:34 am
by hedphelym
Great! Thank you for fixing it so fast.