[Android, Material] Creating a world vector in material gets clamped/broken in OpenGL ES 3.0

Engine Version: 4.7.5 (Launcher Version, C++ project)

Device: Android Galaxy Tab S


We wanted to add an additional dynamic light source for the characters in our mobile game, to make them “pop” more on the screen. We decided to do this by injecting a world vector and making a basic phong-styled layer in the material to add the extra light (only diffuse light). We noticed after deploying to mobile that some devices would get a sharp edge where the light would no longer reach the mesh, no soft transitions. Some characters were even turning dark. After debugging we noticed it was all related to the light source distance, so the light gets cut off.

To reproduce the issue I created a blank C++ project, which you can download [here][5]. I’m using this custom project to demonstrate the issue below.

The custom unlit material in the project looks like this:

This is how the shader should look like. It works on a OpenGL ES2.0 device and on PC.

This is how it looks like when it breaks.

We solved it in our project for now by moving the world position of the light source close enough to the mesh to be within a good distance.

Worth noting is, if I use Get World Position (No Shader Offsets), it seems as if it stops working completely in ES3.0. Works just fine in PC (mobile preview this time).

Hi Denny -

Thank you for your patience. We have been trying to replicate the issue you are experience internally and have not been successful as of yet. I want to ask if you are setting the value of your Material Parameters via a Blueprint (Level or Actor) or are you setting the values directly via a Material Instance or the Material itself? If you are using a Blueprint, can you try it without using the blueprint and see if you can get the light to behave as expected or if it still produces the same results.

Thank you again -

Eric Ketchum

Hi Eric. I’m using this code snippet in C++.

	FVector LightWorldVector = IsValid(LightSourceActor) ? LightSourceActor->GetActorLocation() : FVector(0.0f);

	for (UMaterialInstanceDynamic* MaterialInstance : GeneratedMaterialInstances)
	{
		MaterialInstance->SetVectorParameterValue(TEXT("AmbientLightColor"), AmbientLightColor);
		MaterialInstance->SetVectorParameterValue(TEXT("LightColor"), LightColor);
		MaterialInstance->SetVectorParameterValue(TEXT("LightWorldPosition"), FLinearColor(LightWorldVector));
	}

I only create a blueprint instance of this C++ class to place it in the world. The example project can be found in the original post. I believe I might have an extra if statement for the light world vector to transform a point if there is no valid actor then. Still, both branches give the same result.

I have not tested this on 4.8 preview.

Hey, just deployed this on 4.8 Preview 3. Same problem still. Note that we solved this in our game by just moving the light source closer to each character. So this is not a priority issue for us.

I don’t think it’s the LightWorldVector itself that breaks, or how it is sent to the material, because the location is always correct.

Hi Denny -

We have been running some tests here on your test project and some we have made based on your test project. So far, we have successfully run the code with no issues, but we currently do not have a Galaxy Tab S to test on. I don’t that the issue is device specific like that, we have tested numerous other ES3.0/1 capable Samsung Devices with the same or similar processors without seeing the results you are showing above. We are still testing but this may take some time to nail down what is exactly happening.

Thank You for your patience and if this becomes a complete blocker for you, please let us know immediately here -

Eric Ketchum

This is not a blocker for us Eric, so take your time. We solved it by moving the light source closer to the meshes in question.