[Solved] Detail normal 'value' issue

Discussion area about developing with Ogre2 branches (2.1, 2.2 and beyond)
Post Reply
hedphelym
Gremlin
Posts: 166
Joined: Tue Nov 25, 2008 10:58 am
Location: Kristiansand, Norway
x 10
Contact:

[Solved] Detail normal 'value' issue

Post by hedphelym » Wed Aug 14, 2019 2:57 pm

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?
Last edited by hedphelym on Fri Aug 16, 2019 5:37 am, edited 1 time in total.
0 x

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 4066
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 228
Contact:

Re: Detail normal 'value' issue

Post by dark_sylinc » Thu Aug 15, 2019 1:40 am

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?
0 x

hedphelym
Gremlin
Posts: 166
Joined: Tue Nov 25, 2008 10:58 am
Location: Kristiansand, Norway
x 10
Contact:

Re: Detail normal 'value' issue

Post by hedphelym » Thu Aug 15, 2019 8:23 am

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.
0 x

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 4066
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 228
Contact:

Re: Detail normal 'value' issue

Post by dark_sylinc » Thu Aug 15, 2019 4:26 pm

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!
1 x

hedphelym
Gremlin
Posts: 166
Joined: Tue Nov 25, 2008 10:58 am
Location: Kristiansand, Norway
x 10
Contact:

Re: Detail normal 'value' issue

Post by hedphelym » Thu Aug 15, 2019 4:53 pm

I completely understand. I will see If I can make that tonight.
0 x

hedphelym
Gremlin
Posts: 166
Joined: Tue Nov 25, 2008 10:58 am
Location: Kristiansand, Norway
x 10
Contact:

Re: Detail normal 'value' issue

Post by hedphelym » Thu Aug 15, 2019 9:04 pm

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 );
        }
    }
}
0 x

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 4066
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 228
Contact:

Re: Detail normal 'value' issue

Post by dark_sylinc » Thu Aug 15, 2019 11:40 pm

Fixed. Thanks for the report!
1 x

hedphelym
Gremlin
Posts: 166
Joined: Tue Nov 25, 2008 10:58 am
Location: Kristiansand, Norway
x 10
Contact:

Re: Detail normal 'value' issue

Post by hedphelym » Fri Aug 16, 2019 5:34 am

Great! Thank you for fixing it so fast.
0 x

Post Reply