MShaderManager, OGFX shader and Shadows

MShaderManager, OGFX shader and Shadows

negow
Advocate Advocate
527 Views
3 Replies
Message 1 of 4

MShaderManager, OGFX shader and Shadows

negow
Advocate
Advocate

Hi all,

 

In an MPxSubSceneOverride, when providing my MRenderItem with a factory shader, such as..

myItem->setShader(shaderMgr->getStockShader(
    MHWRender::MShaderManager::k3dBlinnShader
));

Then Maya kindly enables my item to participate in the creation of shadows alongside any other non-subscene related nodes in my Maya scene. And that's great!

 

However, when providing my own OGFX shader, I am unable to find references for where this shadow map is located, along with where the lights are?

myItem->setShader(shaderMgr->getEffectsFileShader(
    "myBlinn.ogsfx", "Main", 0, 0, !reloadShaders
));

 

Let's say for the sake of this example that the below was my shader. Note at the top that I reference a handy overview of uniforms implicitly passed by Maya (thank you kindly!). These are for the view position, the projection matrix and other good things. But no lights!

 

I'm guessing that from looking at the AutodeskUberShader.ogfx that lights are normally passed in explicitly by the plug-in writer. Which I would totally understand.

 

However! Because the factory shaders does such a good job at respecting lights and shadows created unrelated to the node drawn using the subscene override, I'm secretly hoping there are other less-documented uniforms I can implicitly pass to gain access to lights and shadows in the same way that they do.

 

Any ideas?

 

// All available global variables are here
// https://help.autodesk.com/view/MAYAUL/2020/ENU/?guid=GUID-0939A615-81AC-455C-9B23-9ECEC5835F93

// transform object vertices to world-space
uniform mat4 gWorldXf : World;

// transform object vertices to view space and project them in perspective
uniform mat4 gWvpXf : WorldViewProjection;

uniform mat4 gWorldView : ViewProjectionTranspose;

uniform vec3 gLightDir;

/* Data from application vertex buffer */
attribute ToVertex {
    vec3 inPosition   : POSITION;
    vec3 inNormal     : NORMAL;
    vec4 inColor      : COLOR0;
};

attribute ToFragment {
    vec4 Normal         : NORMAL;
    vec4 WorldPosition  : TEXCOORD0;
    vec4 ObjectColor    : COLOR0;

    // Whether or not light should affect the surface color
    float ObjectShading;
};

/* Data output by the fragment shader */
attribute ToScreen  {
    vec4 outColor : COLOR0;
};


GLSLShader ShaderVertex
{
    void main() 
    {
        vec3 worldNormal = normalize(mat3(gWorldXf) * inNormal);
        Normal = vec4(worldNormal, 1.0);
        ObjectColor = vec4(inColor.rgb, 1);
        ObjectShading = inColor.a;

        WorldPosition = gWvpXf * vec4(inPosition, 1);
        WorldPosition.z -= 0.0001;

        gl_Position = WorldPosition;
    }
}

GLSLShader ShaderColor
{
    void main()
    {
        float colorAmount = 0.8;
        float diffuseAmount = 0.2;
        float specularAmount = 0.1;
        float brightness = 1.0;
        float ambient = 0.0;
        int shininess = 2;

        // Diffuse
        vec3 lightColor = vec3(1, 1, 1);
        vec3 norm = normalize(Normal.xyz);
        vec3 lightDir = -normalize(mat3(gWorldView) * gLightDir);
        float diff = max(dot(norm, lightDir), ambient);
        vec3 diffuse = diff * lightColor * diffuseAmount * ObjectShading;

        // Specular
        vec3 viewDir = lightDir;
        vec3 reflectDir = reflect(-lightDir, norm);  
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess);
        vec3 specular = spec * lightColor * specularAmount * ObjectShading;
        vec3 objectColor = ObjectColor.rgb * colorAmount;

        // Composite
        vec3 result = objectColor + diffuse + specular;
        outColor = vec4(result * brightness, 1.0);
    }
}

technique Main
{
    pass p0
    {
        VertexShader (in ToVertex, out ToFragment) = ShaderVertex;
        PixelShader (in ToFragment, out ToScreen) = ShaderColor;
    }
}

 

0 Likes
528 Views
3 Replies
Replies (3)
Message 2 of 4

cheng_xi_li
Autodesk Support
Autodesk Support

Hi,

 

If the factory shader is written with shader fragment. According to the document, if the shader is a surface shader,  the light fragment will be linked dynamically to the fragment. The effect file probably won't be treated the as the same as the shader fragment in Maya now. So it would be better to try to write it with shader fragments. 

 

Yours,

Li

Message 3 of 4

negow
Advocate
Advocate

Thanks, I will investigate MFragmentManager assuming this is what you meant?

 

I also discovered `MDrawContext::getNumberOfActiveLights` along with `::getLightInformation` which seems to provide the raw data I'd need to pass as uniforms to my custom shader. That would save me from having to implement another plug-in altogether.

0 Likes
Message 4 of 4

cheng_xi_li
Autodesk Support
Autodesk Support
The MFragmentManager is one of the framework classes used to create and manage shading fragments. There are also schemas available for the shading fragment in the Maya help.

As you mentioned, there are lights data inside of MDrawContext. If the data from MDrawContext could meet your requirement, it might be easier for you to use in your existing OGSFX shader since shading fragment is a framework based on XML and more Maya flavored.
Yours,
Li