www.jpct.net

jPCT-AE - a 3d engine for Android => Support => Topic started by: AeroShark333 on December 03, 2021, 01:37:22 am

Title: Lighting on merged Object3Ds
Post by: AeroShark333 on December 03, 2021, 01:37:22 am
Hello again,

I'm having some lighting issues when using Object3D.mergeObjects(obj1, obj2)

See image: https://imgur.com/a/aIF67LC

I believe the main cause of this is that the Object3D's overlap..?
(road and the dirt on the side are different layers for instance, at slightly different heights (dirt layer is above road layer).
When rendering it as separate Object3D's the issue is not there.

Any way to solve this without having to flatten the layers in height? I believe the merging of Object3D's messes up the normal vectors or something..? Can this be prevented so it renders similarly as if it were two separate Object3D's?

I'm having similar issues when merging other parts of the scene. Sometimes things appear too bright, sometimes there's dark areas.
It was worse like this before https://imgur.com/a/kfvdjI8 (because one Object3D accidentally had setTransparency, affecting the final merged Object3D...) Removing setTransparency improves it but sometimes there's still random brightly lit parts in the scene.. I wish to get the same visual results as if it was not merged. (Merging seems to boost FPS so that's why..)

Cheers :)

Note:
sideview of road:
Code: [Select]
dirt layer:   ____________                                _____________
road layer:          -----------------------------------------
Title: Re: Lighting on merged Object3Ds
Post by: EgonOlsen on December 03, 2021, 07:14:31 am
The merging does nothing to the normals nor does an overlap, at least not on itself. Are these meshes sharing coordinates? You might want to try to call build() on the objects before merging them and not afterwards to see if that helps.
Title: Re: Lighting on merged Object3Ds
Post by: AeroShark333 on December 08, 2021, 03:22:34 pm
Are these meshes sharing coordinates?
No, but they are usually very close (almost negligible), though probably they don't get merged to be using them as the same coordinates as they are still slightly different.

You might want to try to call build() on the objects before merging them and not afterwards to see if that helps.
This didn't work

I fixed part of the issue by making them share coordinates (I believe the overlap makes the lower layer 'unlit..'..? or something)
But I still have the lighting issue for some other parts (but these appear too bright..? for unknown reason, they also flicker)

EDIT: Images for clarification: https://imgur.com/a/FYNF3Wm
It might not seem like a lot in the images, but it flickers from dark to bright so it is very noticable in that way
Title: Re: Lighting on merged Object3Ds
Post by: EgonOlsen on December 10, 2021, 03:34:44 pm
Each object will be lit by itself, no matter how they overlap with each other. Regarding the lighting, they are completely independant. Maybe it's just caused by way in which the normals are created? A vertex normal is calculated by taking the face normals of the adjacent polygons and averaging them. If you, for example, stack boxes onto another the normals on the lower corners will face something like 45° down while the ones on the upper corners will face 45° up. That will cause uneven lighting on something like a wall that consists of these boxes.

Title: Re: Lighting on merged Object3Ds
Post by: AeroShark333 on December 10, 2021, 10:01:04 pm
Each object will be lit by itself, no matter how they overlap with each other. Regarding the lighting, they are completely independant. Maybe it's just caused by way in which the normals are created? A vertex normal is calculated by taking the face normals of the adjacent polygons and averaging them. If you, for example, stack boxes onto another the normals on the lower corners will face something like 45° down while the ones on the upper corners will face 45° up. That will cause uneven lighting on something like a wall that consists of these boxes.
Is it possible to merge Object3D's without these vertices being combined (or normals being recalculated) but instead literally keep the original meshes and add them together (non-optimized), so that the normals stay as the original Object3D's? (if this makes sense)
Title: Re: Lighting on merged Object3Ds
Post by: EgonOlsen on December 11, 2021, 07:40:22 pm
Actually, if the normals have been calculated (or loaded from file with Config.useNormalsFromOBJ=true) already before merging, they won't be recalculated after the merge when you call build on the merged object. I'm not sure if your issue is related to merging at all, though. I rather think it's caused by normal vectors that aren't calculated in a why that fits your scene. Does the file from which these objects come includes normals? In that case, you could try the config switch mentioned above.
Title: Re: Lighting on merged Object3Ds
Post by: AeroShark333 on December 12, 2021, 04:32:09 am
Actually, if the normals have been calculated (or loaded from file with Config.useNormalsFromOBJ=true) already before merging, they won't be recalculated after the merge when you call build on the merged object. I'm not sure if your issue is related to merging at all, though. I rather think it's caused by normal vectors that aren't calculated in a why that fits your scene. Does the file from which these objects come includes normals? In that case, you could try the config switch mentioned above.
I'm not using models from files, but I create them using Object3D#addTriangle (as they are simple planes sort of...)
I don't think the Config switch would do anything for this...

I was able to create a test case, however... (it doesn't look amazing but it shows the problem I guess...)
Code: [Select]
final GLSurfaceView.Renderer testRenderer = new GLSurfaceView.Renderer() {
                private FrameBuffer frameBuffer;
                private World world;
                private Object3D master;
                private Object3D plane1;
                private Object3D plane2;
                private Object3D plane3;
                private Camera camera;

                @Override
                public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {

                }

                @Override
                public void onSurfaceChanged(GL10 gl10, int w, int h) {
                    Config.nearPlane = 1f;
                    Config.glIgnoreNearPlane = false;

                    frameBuffer = new FrameBuffer(w, h);
                    world = new World();
                    world.setAmbientLight(0, 0, 0);
                    Light l1 = new Light(world);
                    l1.setPosition(new SimpleVector(0f, 6f, 0f));
                    camera = world.getCamera();

                    final Texture sphereTexture = new Texture(2, 2, new RGBColor(75, 0, 0));
                    final Texture overlayTexture = new Texture(2, 2, new RGBColor(0, 0, 75));
                    final Texture planeTexture = new Texture(2, 2, new RGBColor(0, 75, 0));

                    final TextureManager textureManager = TextureManager.getInstance();
                    textureManager.addTexture("tex0", sphereTexture);
                    textureManager.addTexture("tex1", overlayTexture);
                    textureManager.addTexture("tex2", planeTexture);

                    master = Object3D.createDummyObj();

                    plane1 = new Object3D(4);
                    plane2 = new Object3D(8);
                    plane3 = new Object3D(8);

                    plane1.addTriangle(new SimpleVector(-5.55, -0.941941941, -1.0), 0.0f, 0.0f, new SimpleVector(-5.55, -0.941941941, 1.0), 0.0f, 1.0f, new SimpleVector(5.55, -0.941941941, -1.0), 1.0f, 0.0f);
                    plane1.addTriangle(new SimpleVector(5.55, -0.941941941, 1.0), 1.0f, 1.0f, new SimpleVector(5.55, -0.941941941, -1.0), 1.0f, 0.0f, new SimpleVector(-5.55, -0.941941941, 1.0), 0.0f, 1.0f);
                    //roadMaster.setAdditionalColor(100, 100, 100);

                    plane1.setAdditionalColor(100, 100, 100);
                    plane1.compile(false, true);
                    plane1.strip();
                    plane1.build();
                    plane1.setTexture("tex0");

                    plane2.addTriangle(new SimpleVector(-6.6, -0.939, -1.02), 0.5f, 0.0f, new SimpleVector(-6.6, -0.939, 1.02), 0.5f, 1.0f, new SimpleVector(-5.55, -0.941941941, -1.02), 1.0f, 0.0f);
                    plane2.addTriangle(new SimpleVector(-5.55, -0.941941941, 1.02), 1.0f, 1.0f, new SimpleVector(-5.55, -0.941941941, -1.02), 1.0f, 0.0f, new SimpleVector(-6.6, -0.939, 1.02), 0.5f, 1.0f);
                    plane2.addTriangle(new SimpleVector(5.55, -0.941941941, -1.02), 0.0f, 0.0f, new SimpleVector(5.55, -0.941941941, 1.02), 0.0f, 1.0f, new SimpleVector(6.6, -0.939, -1.02), 0.5f, 0.0f);
                    plane2.addTriangle(new SimpleVector(6.6, -0.939, 1.02), 0.5f, 1.0f, new SimpleVector(6.6, -0.939, -1.02), 0.5f, 0.0f, new SimpleVector(5.55, -0.941941941, 1.02), 0.0f, 1.0f);

                    plane2.setAdditionalColor(100, 100, 100);
                    plane2.compile(false, true);
                    plane2.strip();
                    plane2.build();
                    plane2.setTexture("tex1");

                    float heightMultiplier = 333f;
                    float lastHeightLeft = 0.03f;
                    float newHeightLeft = 0.024f;
                    float newHeightRight = 0.012f;
                    float lastHeightRight = 0.01f;

                    // base

                    plane3.setAdditionalColor(100, 100, 100);
                    plane3.addTriangle(new SimpleVector(-11.4f, lastHeightLeft * heightMultiplier / 3f, -1.02), 0.5f, 0.0f, new SimpleVector(-11.4f, newHeightLeft * heightMultiplier / 3f, 1.02), 0.5f, 1.0f, new SimpleVector(-6.6f, -0.939, -1.02), 1.0f, 0.0f);
                    plane3.addTriangle(new SimpleVector(-6.6f, -0.939, 1.02), 1.0f, 1.0f, new SimpleVector(-6.6f, -0.939, -1.02), 1.0f, 0.0f, new SimpleVector(-11.4f, newHeightLeft * heightMultiplier / 3f, 1.02), 0.5f, 1.0f);
                    plane3.addTriangle(new SimpleVector(6.6f, -0.939, -1.02), 0.0f, 0.0f, new SimpleVector(6.6f, -0.939, 1.02), 0.0f, 1.0f, new SimpleVector(11.4f, lastHeightRight * heightMultiplier / 3f, -1.02), 0.5f, 0.0f);
                    plane3.addTriangle(new SimpleVector(11.4f, newHeightRight * heightMultiplier / 3f, 1.02), 0.5f, 1.0f, new SimpleVector(11.4f, lastHeightRight * heightMultiplier / 3f, -1.02), 0.5f, 0.0f, new SimpleVector(6.6f, -0.939, 1.02), 0.0f, 1.0f);
                    plane3.setTexture("tex2");
                    plane3.build();

                    boolean merge = false;

                    if(merge){
                        Object3D mergeObj = Object3D.mergeObjects(plane1, plane2);
                        mergeObj = Object3D.mergeObjects(plane3, mergeObj);
                        world.addObject( mergeObj);
                    }else {
                        world.addObject(plane1);
                        world.addObject(plane2);
                        world.addObject(plane3);

                        Object3D mergeObj = Object3D.mergeObjects(plane1, plane2);
                        mergeObj = Object3D.mergeObjects(plane3, mergeObj);
                        world.addObject( mergeObj);
                        mergeObj.setSpecularLighting(false);
                        mergeObj.translate(0,0,3f);
                    }
                }

                @Override
                public void onDrawFrame(GL10 gl10) {
                    frameBuffer.clear();
                    final float maxDistance = 150f;
                    camera.setPosition(-(0.5f * ((float) Math.abs(Math.cos(world.getFrameCounter() * 0.03f))) + 0.25f) * maxDistance, 30f, 0f);
                    camera.lookAt(new SimpleVector(0,0,0));
                    world.renderScene(frameBuffer);
                    world.draw(frameBuffer);
                    frameBuffer.display();
                }
            };

            // Attach to some GLSurfaceView...
            viewer.setRenderer(testRenderer);

Results: https://imgur.com/a/KffOw9m (left = merged object, right = not merged objects)
The first two images show the same but at a slightly different camera distance/angle, and you can see that the green tile on the left object is slightly darker than the in the second image.
In the last image, you can see some shading pattern on the red and green on the left object.

These do share coordinates however... maybe that nullifies the build() effect...

EDIT:
Okay... apparently it still happens when the coordinates are NOT shared...
So now I don't understand why build() didn't work...

Code snippet for non-sharing coordinates (replace these lines in the test case...):
Code: [Select]
plane2.addTriangle(new SimpleVector(-6.6, - 0.9, -1.02), 0.5f, 0.0f, new SimpleVector(-6.6, - 0.9, 1.02), 0.5f, 1.0f, new SimpleVector(-5.55, - 0.9, -1.02), 1.0f, 0.0f);
                    plane2.addTriangle(new SimpleVector(-5.55, - 0.9, 1.02), 1.0f, 1.0f, new SimpleVector(-5.55, - 0.9, -1.02), 1.0f, 0.0f, new SimpleVector(-6.6, - 0.9, 1.02), 0.5f, 1.0f);
                    plane2.addTriangle(new SimpleVector(5.55, - 0.9, -1.02), 0.0f, 0.0f, new SimpleVector(5.55, - 0.9, 1.02), 0.0f, 1.0f, new SimpleVector(6.6, - 0.9, -1.02), 0.5f, 0.0f);
                    plane2.addTriangle(new SimpleVector(6.6, - 0.9, 1.02), 0.5f, 1.0f, new SimpleVector(6.6, - 0.9, -1.02), 0.5f, 0.0f, new SimpleVector(5.55, - 0.9, 1.02), 0.0f, 1.0f);

                    plane2.setAdditionalColor(100, 100, 100);
                    plane2.compile(false, true);
                    plane2.strip();
                    plane2.build();
                    plane2.setTexture("tex1");

                    float heightMultiplier = 333f;
                    float lastHeightLeft = 0.03f;
                    float newHeightLeft = 0.024f;
                    float newHeightRight = 0.012f;
                    float lastHeightRight = 0.01f;

                    // base

                    plane3.setAdditionalColor(100, 100, 100);
                    plane3.addTriangle(new SimpleVector(-11.4f, lastHeightLeft * heightMultiplier / 3f, -1.02), 0.5f, 0.0f, new SimpleVector(-11.4f, newHeightLeft * heightMultiplier / 3f, 1.02), 0.5f, 1.0f, new SimpleVector(-6.6f, -0.941941941, -1.02), 1.0f, 0.0f);
                    plane3.addTriangle(new SimpleVector(-6.6f, -0.941941941, 1.02), 1.0f, 1.0f, new SimpleVector(-6.6f, -0.941941941, -1.02), 1.0f, 0.0f, new SimpleVector(-11.4f, newHeightLeft * heightMultiplier / 3f, 1.02), 0.5f, 1.0f);
                    plane3.addTriangle(new SimpleVector(6.6f, -0.941941941, -1.02), 0.0f, 0.0f, new SimpleVector(6.6f, -0.941941941, 1.02), 0.0f, 1.0f, new SimpleVector(11.4f, lastHeightRight * heightMultiplier / 3f, -1.02), 0.5f, 0.0f);
                    plane3.addTriangle(new SimpleVector(11.4f, newHeightRight * heightMultiplier / 3f, 1.02), 0.5f, 1.0f, new SimpleVector(11.4f, lastHeightRight * heightMultiplier / 3f, -1.02), 0.5f, 0.0f, new SimpleVector(6.6f, -0.941941941, 1.02), 0.0f, 1.0f);
                    plane3.setTexture("tex2");
                    plane3.build();

EDIT2: I forgot to set the additionalColor on the merged object... Just forget everything above...
Here is a test case without any additionalColor:
Code: [Select]
final GLSurfaceView.Renderer testRenderer = new GLSurfaceView.Renderer() {
                private FrameBuffer frameBuffer;
                private World world;
                private Object3D master;
                private Object3D plane1;
                private Object3D plane2;
                private Object3D plane3;
                private Camera camera;

                @Override
                public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {

                }

                @Override
                public void onSurfaceChanged(GL10 gl10, int w, int h) {
                    Config.nearPlane = 1f;
                    Config.glIgnoreNearPlane = false;

                    frameBuffer = new FrameBuffer(w, h);
                    world = new World();
                    world.setAmbientLight(0, 0, 0);
                    Light l1 = new Light(world);
                    l1.setPosition(new SimpleVector(0f, 6f, 0f));
                    camera = world.getCamera();

                    final Texture sphereTexture = new Texture(2, 2, new RGBColor(75, 0, 0));
                    final Texture overlayTexture = new Texture(2, 2, new RGBColor(0, 0, 75));
                    final Texture planeTexture = new Texture(2, 2, new RGBColor(0, 75, 0));

                    final TextureManager textureManager = TextureManager.getInstance();
                    textureManager.addTexture("tex0", sphereTexture);
                    textureManager.addTexture("tex1", overlayTexture);
                    textureManager.addTexture("tex2", planeTexture);

                    master = Object3D.createDummyObj();

                    plane1 = new Object3D(4);
                    plane2 = new Object3D(8);
                    plane3 = new Object3D(8);

                    plane1.addTriangle(new SimpleVector(-5.55, -0.941941941, -1.0), 0.0f, 0.0f, new SimpleVector(-5.55, -0.941941941, 1.0), 0.0f, 1.0f, new SimpleVector(5.55, -0.941941941, -1.0), 1.0f, 0.0f);
                    plane1.addTriangle(new SimpleVector(5.55, -0.941941941, 1.0), 1.0f, 1.0f, new SimpleVector(5.55, -0.941941941, -1.0), 1.0f, 0.0f, new SimpleVector(-5.55, -0.941941941, 1.0), 0.0f, 1.0f);
                    //roadMaster.setAdditionalColor(100, 100, 100);

                    //plane1.setAdditionalColor(100, 100, 100);
                    plane1.compile(false, true);
                    plane1.strip();
                    plane1.build();
                    plane1.setTexture("tex0");

                    plane2.addTriangle(new SimpleVector(-6.6, - 0.9, -1.02), 0.5f, 0.0f, new SimpleVector(-6.6, - 0.9, 1.02), 0.5f, 1.0f, new SimpleVector(-5.55, - 0.9, -1.02), 1.0f, 0.0f);
                    plane2.addTriangle(new SimpleVector(-5.55, - 0.9, 1.02), 1.0f, 1.0f, new SimpleVector(-5.55, - 0.9, -1.02), 1.0f, 0.0f, new SimpleVector(-6.6, - 0.9, 1.02), 0.5f, 1.0f);
                    plane2.addTriangle(new SimpleVector(5.55, - 0.9, -1.02), 0.0f, 0.0f, new SimpleVector(5.55, - 0.9, 1.02), 0.0f, 1.0f, new SimpleVector(6.6, - 0.9, -1.02), 0.5f, 0.0f);
                    plane2.addTriangle(new SimpleVector(6.6, - 0.9, 1.02), 0.5f, 1.0f, new SimpleVector(6.6, - 0.9, -1.02), 0.5f, 0.0f, new SimpleVector(5.55, - 0.9, 1.02), 0.0f, 1.0f);

                    //plane2.setAdditionalColor(100, 100, 100);
                    plane2.compile(false, true);
                    plane2.strip();
                    plane2.build();
                    plane2.setTexture("tex1");

                    float heightMultiplier = 333f;
                    float lastHeightLeft = 0.03f;
                    float newHeightLeft = 0.024f;
                    float newHeightRight = 0.012f;
                    float lastHeightRight = 0.01f;

                    // base

                    //plane3.setAdditionalColor(100, 100, 100);
                    plane3.addTriangle(new SimpleVector(-11.4f, lastHeightLeft * heightMultiplier / 3f, -1.02), 0.5f, 0.0f, new SimpleVector(-11.4f, newHeightLeft * heightMultiplier / 3f, 1.02), 0.5f, 1.0f, new SimpleVector(-6.6f, -0.941941941, -1.02), 1.0f, 0.0f);
                    plane3.addTriangle(new SimpleVector(-6.6f, -0.941941941, 1.02), 1.0f, 1.0f, new SimpleVector(-6.6f, -0.941941941, -1.02), 1.0f, 0.0f, new SimpleVector(-11.4f, newHeightLeft * heightMultiplier / 3f, 1.02), 0.5f, 1.0f);
                    plane3.addTriangle(new SimpleVector(6.6f, -0.941941941, -1.02), 0.0f, 0.0f, new SimpleVector(6.6f, -0.941941941, 1.02), 0.0f, 1.0f, new SimpleVector(11.4f, lastHeightRight * heightMultiplier / 3f, -1.02), 0.5f, 0.0f);
                    plane3.addTriangle(new SimpleVector(11.4f, newHeightRight * heightMultiplier / 3f, 1.02), 0.5f, 1.0f, new SimpleVector(11.4f, lastHeightRight * heightMultiplier / 3f, -1.02), 0.5f, 0.0f, new SimpleVector(6.6f, -0.941941941, 1.02), 0.0f, 1.0f);
                    plane3.setTexture("tex2");
                    plane3.build();

                    boolean merge = false;

                    if(merge){
                        Object3D mergeObj = Object3D.mergeObjects(plane1, plane2);
                        mergeObj = Object3D.mergeObjects(plane3, mergeObj);
                        //mergeObj.setAdditionalColor(100, 100, 100);
                        world.addObject( mergeObj);
                    }else {
                        world.addObject(plane1);
                        world.addObject(plane2);
                        world.addObject(plane3);

                        Object3D mergeObj = Object3D.mergeObjects(plane1, plane2);
                        mergeObj = Object3D.mergeObjects(plane3, mergeObj);
                        world.addObject( mergeObj);
                        //mergeObj.setAdditionalColor(100, 100, 100);
                        mergeObj.translate(0,0,3f);
                        plane1.translate(0,0,-3f);
                        plane2.translate(0,0,-3f);
                        plane3.translate(0,0,-3f);
                    }
                }

                @Override
                public void onDrawFrame(GL10 gl10) {
                    frameBuffer.clear();
                    final float maxDistance = 150f;
                    camera.setPosition(-(0.5f * ((float) Math.abs(Math.cos(world.getFrameCounter() * 0.03f))) + 0.25f) * maxDistance, 30f, 0f);
                    camera.lookAt(new SimpleVector(0,0,0));
                    world.renderScene(frameBuffer);
                    world.draw(frameBuffer);
                    frameBuffer.display();
                }
            };

            // Attach to some GLSurfaceView...
            viewer.setRenderer(testRenderer);

EDIT3: An animated image for the last test case: https://imgur.com/a/wR8MqgG
I believe I get similar-ish results but it gets brighter for me randomly but I guess it's a similar idea

EDIT4: I have a slight feeling this issue is there because the merged Object3D is multi-textured..? I'm not entirely sure...
The issue seems to disappear if it has 1 or 2 different textures only (but when you add the third, the lighting seems to behave differently)
Title: Re: Lighting on merged Object3Ds
Post by: EgonOlsen on December 13, 2021, 06:04:51 pm
Honestly, I'm not sure what I'm supposed to see on these images!? The last one (the one with the animation) doesn't work for me on the desktop. I can view it on my phone though, but all I'm seeing are two bouncing planes...I'm not sure what to look out for, they look fine (albeit highly compressed) to me.

Anyway, the lighting calculation done by the default shaders doesn't depend on the number of texture stages. It just multiplies the calculated light color/intensity with the pixel after all texture stages have been blended together. If one texture is very dark or the blending mode is some unusual one, the results might not be what one expects, but I don't think that this is the case here.

Looking at your code, you:


I suggest to do this instead:


I don't think that this will change something but it's actually the way it's intended to be done and maybe your way has some effect on something that I don't see ATM.
Title: Re: Lighting on merged Object3Ds
Post by: AeroShark333 on December 14, 2021, 08:38:00 pm
I changed the code to your suggestions (see below):

Here are the animations:
https://imgur.com/a/Jk8zt2g
https://imgur.com/a/Zwxem7I

Code:
Code: [Select]
final GLSurfaceView.Renderer testRenderer = new GLSurfaceView.Renderer() {
                private FrameBuffer frameBuffer;
                private World world;
                private Object3D master;
                private Object3D plane1;
                private Object3D plane2;
                private Object3D plane3;
                private Camera camera;

                @Override
                public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {

                }

                @Override
                public void onSurfaceChanged(GL10 gl10, int w, int h) {
                    Config.nearPlane = 1f;
                    Config.glIgnoreNearPlane = false;

                    frameBuffer = new FrameBuffer(w, h);
                    world = new World();
                    world.setAmbientLight(0, 0, 0);
                    Light l1 = new Light(world);
                    l1.setPosition(new SimpleVector(0f, 6f, 0f));
                    camera = world.getCamera();

                    final Texture sphereTexture = new Texture(2, 2, new RGBColor(75, 0, 0));
                    final Texture overlayTexture = new Texture(2, 2, new RGBColor(0, 0, 75));
                    final Texture planeTexture = new Texture(2, 2, new RGBColor(0, 75, 0));

                    final TextureManager textureManager = TextureManager.getInstance();
                    textureManager.addTexture("tex0", sphereTexture);
                    textureManager.addTexture("tex1", overlayTexture);
                    textureManager.addTexture("tex2", planeTexture);

                    master = Object3D.createDummyObj();

                    plane1 = new Object3D(4);
                    plane2 = new Object3D(8);
                    plane3 = new Object3D(8);

                    plane1.addTriangle(new SimpleVector(-5.55, -0.941941941, -1.0), 0.0f, 0.0f, new SimpleVector(-5.55, -0.941941941, 1.0), 0.0f, 1.0f, new SimpleVector(5.55, -0.941941941, -1.0), 1.0f, 0.0f);
                    plane1.addTriangle(new SimpleVector(5.55, -0.941941941, 1.0), 1.0f, 1.0f, new SimpleVector(5.55, -0.941941941, -1.0), 1.0f, 0.0f, new SimpleVector(-5.55, -0.941941941, 1.0), 0.0f, 1.0f);
                    //roadMaster.setAdditionalColor(100, 100, 100);

                    //plane1.setAdditionalColor(100, 100, 100);
                    //plane1.compile(false, true);
                    //plane1.strip();
                    //plane1.build();
                    plane1.setTexture("tex0");

                    plane2.addTriangle(new SimpleVector(-6.6, - 0.9, -1.02), 0.5f, 0.0f, new SimpleVector(-6.6, - 0.9, 1.02), 0.5f, 1.0f, new SimpleVector(-5.55, - 0.9, -1.02), 1.0f, 0.0f);
                    plane2.addTriangle(new SimpleVector(-5.55, - 0.9, 1.02), 1.0f, 1.0f, new SimpleVector(-5.55, - 0.9, -1.02), 1.0f, 0.0f, new SimpleVector(-6.6, - 0.9, 1.02), 0.5f, 1.0f);
                    plane2.addTriangle(new SimpleVector(5.55, - 0.9, -1.02), 0.0f, 0.0f, new SimpleVector(5.55, - 0.9, 1.02), 0.0f, 1.0f, new SimpleVector(6.6, - 0.9, -1.02), 0.5f, 0.0f);
                    plane2.addTriangle(new SimpleVector(6.6, - 0.9, 1.02), 0.5f, 1.0f, new SimpleVector(6.6, - 0.9, -1.02), 0.5f, 0.0f, new SimpleVector(5.55, - 0.9, 1.02), 0.0f, 1.0f);

                    //plane2.setAdditionalColor(100, 100, 100);
                    //plane2.compile(false, true);
                    //plane2.strip();
                    //plane2.build();
                    plane2.setTexture("tex1");

                    float heightMultiplier = 333f;
                    float lastHeightLeft = 0.03f;
                    float newHeightLeft = 0.024f;
                    float newHeightRight = 0.012f;
                    float lastHeightRight = 0.01f;

                    // base

                    //plane3.setAdditionalColor(100, 100, 100);
                    plane3.addTriangle(new SimpleVector(-11.4f, lastHeightLeft * heightMultiplier / 3f, -1.02), 0.5f, 0.0f, new SimpleVector(-11.4f, newHeightLeft * heightMultiplier / 3f, 1.02), 0.5f, 1.0f, new SimpleVector(-6.6f, -0.941941941, -1.02), 1.0f, 0.0f);
                    plane3.addTriangle(new SimpleVector(-6.6f, -0.941941941, 1.02), 1.0f, 1.0f, new SimpleVector(-6.6f, -0.941941941, -1.02), 1.0f, 0.0f, new SimpleVector(-11.4f, newHeightLeft * heightMultiplier / 3f, 1.02), 0.5f, 1.0f);
                    plane3.addTriangle(new SimpleVector(6.6f, -0.941941941, -1.02), 0.0f, 0.0f, new SimpleVector(6.6f, -0.941941941, 1.02), 0.0f, 1.0f, new SimpleVector(11.4f, lastHeightRight * heightMultiplier / 3f, -1.02), 0.5f, 0.0f);
                    plane3.addTriangle(new SimpleVector(11.4f, newHeightRight * heightMultiplier / 3f, 1.02), 0.5f, 1.0f, new SimpleVector(11.4f, lastHeightRight * heightMultiplier / 3f, -1.02), 0.5f, 0.0f, new SimpleVector(6.6f, -0.941941941, 1.02), 0.0f, 1.0f);
                    plane3.setTexture("tex2");
                    //plane3.build();

                    boolean merge = false;

                    if(merge){
                        Object3D mergeObj = Object3D.mergeObjects(plane1, plane2);
                        mergeObj = Object3D.mergeObjects(plane3, mergeObj);
                        //mergeObj.setAdditionalColor(100, 100, 100);
                        mergeObj.build();
                        mergeObj.compile(false, true);
                        mergeObj.strip();
                        world.addObject( mergeObj);
                    }else {
                        world.addObject(plane1);
                        world.addObject(plane2);
                        world.addObject(plane3);

                        Object3D mergeObj = Object3D.mergeObjects(plane1, plane2);
                        mergeObj = Object3D.mergeObjects(plane3, mergeObj);
                        world.addObject( mergeObj);
                        //mergeObj.setAdditionalColor(100, 100, 100);
                        mergeObj.translate(0,0,3f);
                        plane1.translate(0,0,-3f);
                        plane2.translate(0,0,-3f);
                        plane3.translate(0,0,-3f);
                    }
                }

                @Override
                public void onDrawFrame(GL10 gl10) {
                    frameBuffer.clear();
                    final float maxDistance = 150f;
                    camera.setPosition(-(0.5f * ((float) Math.abs(Math.cos(world.getFrameCounter() * 0.03f))) + 0.25f) * maxDistance, 30f, 0f);
                    camera.lookAt(new SimpleVector(0,4.5f,0));
                    world.renderScene(frameBuffer);
                    world.draw(frameBuffer);
                    frameBuffer.display();
                }
            };

            // Attach to some GLSurfaceView...
            viewer.setRenderer(testRenderer);

If I do:
Code: [Select]
plane2.setTexture("tex2");the problem disappears..?  ???
Title: Re: Lighting on merged Object3Ds
Post by: EgonOlsen on December 17, 2021, 05:29:42 pm
Have you tried to create larger textures? Maybe it's a rendering glitch caused by the small size and mip-mapping somehow?
Title: Re: Lighting on merged Object3Ds
Post by: AeroShark333 on December 28, 2021, 01:33:08 am
Have you tried to create larger textures? Maybe it's a rendering glitch caused by the small size and mip-mapping somehow?
I tried:
Code: [Select]
final Texture sphereTexture = new Texture(2048, 2048, new RGBColor(75, 0, 0));
                    final Texture overlayTexture = new Texture(2048, 2048, new RGBColor(0, 0, 75));
                    final Texture planeTexture = new Texture(2048, 2048, new RGBColor(0, 75, 0));

                    sphereTexture.setMipmap(false);
                    overlayTexture.setMipmap(false);
                    planeTexture.setMipmap(false);
Both true and false for mip-mapping. Seems to behave as before.
Title: Re: Lighting on merged Object3Ds
Post by: EgonOlsen on December 30, 2021, 04:41:12 pm
I'm not sure if what's going on then, but then again, I'm not sure what the actual issue really is. The videos don't really make it clear to me. Can you create something that is more, well, obvious?
Title: Re: Lighting on merged Object3Ds
Post by: AeroShark333 on January 04, 2022, 04:01:04 am
I'm not sure if what's going on then, but then again, I'm not sure what the actual issue really is. The videos don't really make it clear to me. Can you create something that is more, well, obvious?
I'm not sure if this is any helpful but I enlarged the shapes..? Well... here goes:

Explanation:
If the sphere on the right is visible, then it will only render the merged Object3D.
If the sphere on the right is NOT visible, then it will only render the unmerged Object3Ds.
The merged Object3D consists of the unmerged Object3Ds.

Expectation:
Similar visuals for both scenarios

Result:
Not similar visuals; there seem to be lighting differences (bugs?)
Only when all of the unmerged Object3Ds use 1 texture (instead of 2 or 3 different textures), the bug seems to disappear.

Video proof:
https://imgur.com/a/Ox51NRL
https://imgur.com/a/Ag76Sml (different texture variations)

Test code (for reproducing):
Code: [Select]
final GLSurfaceView.Renderer testRenderer = new GLSurfaceView.Renderer() {
                private FrameBuffer frameBuffer;
                private World world;
                private Object3D master;
                private Object3D plane1;
                private Object3D plane2;
                private Object3D plane3;
                private Camera camera;
                private boolean offset = false;
                private Object3D mergeObj;

                @Override
                public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {

                }

                @Override
                public void onSurfaceChanged(GL10 gl10, int w, int h) {
                    Config.nearPlane = 1f;
                    Config.glIgnoreNearPlane = false;

                    frameBuffer = new FrameBuffer(w, h);
                    world = new World();
                    world.setAmbientLight(0, 0, 0);
                    Light l1 = new Light(world);
                    l1.setPosition(new SimpleVector(0f, 6f, 0f));
                    camera = world.getCamera();

                    final Texture sphereTexture = new Texture(2, 2, new RGBColor(75, 0, 0));
                    final Texture overlayTexture = new Texture(2, 2, new RGBColor(0, 0, 75));
                    final Texture planeTexture = new Texture(2, 2, new RGBColor(0, 75, 0));
                    final Texture whiteTexture = new Texture(2,2, new RGBColor(255,255,255));

                    final TextureManager textureManager = TextureManager.getInstance();
                    textureManager.addTexture("tex0", sphereTexture);
                    textureManager.addTexture("tex1", overlayTexture);
                    textureManager.addTexture("tex2", planeTexture);
                    textureManager.addTexture("tex3", whiteTexture);

                    //master = Object3D.createDummyObj();

                    plane1 = new Object3D(4);
                    plane2 = new Object3D(8);
                    plane3 = new Object3D(8);

                    master = ExtendedPrimitives.createSphere(3.0f,60);
                    master.setTexture("tex3");

                    plane1.addTriangle(new SimpleVector(-5.55, -0.941941941, -4.5), 0.0f, 0.0f, new SimpleVector(-5.55, -0.941941941, 4.5), 0.0f, 4.5f, new SimpleVector(5.55, -0.941941941, -4.5), 4.5f, 0.0f);
                    plane1.addTriangle(new SimpleVector(5.55, -0.941941941, 4.5), 4.5f, 4.5f, new SimpleVector(5.55, -0.941941941, -4.5), 4.5f, 0.0f, new SimpleVector(-5.55, -0.941941941, 4.5), 0.0f, 4.5f);
                    //roadMaster.setAdditionalColor(100, 100, 100);

                    //plane1.setAdditionalColor(100, 100, 100);
                    //plane1.compile(false, true);
                    //plane1.strip();
                    //plane1.build();
                    plane1.setTexture("tex0");

                    plane2.addTriangle(new SimpleVector(-6.6, -0.9, -4.52), 0.5f, 0.0f, new SimpleVector(-6.6, -0.9, 4.52), 0.5f, 4.5f, new SimpleVector(-5.55, -0.9, -4.52), 4.5f, 0.0f);
                    plane2.addTriangle(new SimpleVector(-5.55, -0.9, 4.52), 4.5f, 4.5f, new SimpleVector(-5.55, -0.9, -4.52), 4.5f, 0.0f, new SimpleVector(-6.6, -0.9, 4.52), 0.5f, 4.5f);
                    plane2.addTriangle(new SimpleVector(5.55, -0.9, -4.52), 0.0f, 0.0f, new SimpleVector(5.55, -0.9, 4.52), 0.0f, 4.5f, new SimpleVector(6.6, -0.9, -4.52), 0.5f, 0.0f);
                    plane2.addTriangle(new SimpleVector(6.6, -0.9, 4.52), 0.5f, 4.5f, new SimpleVector(6.6, -0.9, -4.52), 0.5f, 0.0f, new SimpleVector(5.55, -0.9, 4.52), 0.0f, 4.5f);

                    //plane2.setAdditionalColor(100, 100, 100);
                    //plane2.compile(false, true);
                    //plane2.strip();
                    //plane2.build();
                    plane2.setTexture("tex1");

                    float heightMultiplier = 333f;
                    float lastHeightLeft = 0.03f;
                    float newHeightLeft = 0.024f;
                    float newHeightRight = 0.012f;
                    float lastHeightRight = 0.01f;

                    // base

                    //plane3.setAdditionalColor(100, 100, 100);
                    plane3.addTriangle(new SimpleVector(-11.4f, lastHeightLeft * heightMultiplier / 3f, -4.52), 0.5f, 0.0f, new SimpleVector(-11.4f, newHeightLeft * heightMultiplier / 3f, 4.52), 0.5f, 4.5f, new SimpleVector(-6.6f, -0.941941941, -4.52), 4.5f, 0.0f);
                    plane3.addTriangle(new SimpleVector(-6.6f, -0.941941941, 4.52), 4.5f, 4.5f, new SimpleVector(-6.6f, -0.941941941, -4.52), 4.5f, 0.0f, new SimpleVector(-11.4f, newHeightLeft * heightMultiplier / 3f, 4.52), 0.5f, 4.5f);
                    plane3.addTriangle(new SimpleVector(6.6f, -0.941941941, -4.52), 0.0f, 0.0f, new SimpleVector(6.6f, -0.941941941, 4.52), 0.0f, 4.5f, new SimpleVector(11.4f, lastHeightRight * heightMultiplier / 3f, -4.52), 0.5f, 0.0f);
                    plane3.addTriangle(new SimpleVector(11.4f, newHeightRight * heightMultiplier / 3f, 4.52), 0.5f, 4.5f, new SimpleVector(11.4f, lastHeightRight * heightMultiplier / 3f, -4.52), 0.5f, 0.0f, new SimpleVector(6.6f, -0.941941941, 4.52), 0.0f, 4.5f);
                    plane3.setTexture("tex2");
                    //plane3.build();

                    boolean merge = false;

                    if (merge) {
                        mergeObj = Object3D.mergeObjects(plane1, plane2);
                        mergeObj = Object3D.mergeObjects(plane3, mergeObj);
                        //mergeObj.setAdditionalColor(100, 100, 100);
                        mergeObj.build();
                        mergeObj.compile(false, true);
                        mergeObj.strip();
                        world.addObject(mergeObj);
                    } else {
                        world.addObject(plane1);
                        world.addObject(plane2);
                        world.addObject(plane3);

                        mergeObj = Object3D.mergeObjects(plane1, plane2);
                        mergeObj = Object3D.mergeObjects(plane3, mergeObj);
                        world.addObject(mergeObj);
                        //mergeObj.setAdditionalColor(100, 100, 100);
                        if(offset) {
                            mergeObj.translate(0, 0, 6f);
                            plane1.translate(0, 0, -6f);
                            plane2.translate(0, 0, -6f);
                            plane3.translate(0, 0, -6f);
                        }else{
                            mergeObj.translate(0, 0, 6f);
                            plane1.translate(0, 0, 6f);
                            plane2.translate(0, 0, 6f);
                            plane3.translate(0, 0, 6f);
                            world.addObject(master);
                            master.translate(0,6f,-6f);
                        }
                        mergeObj.build();
                    }
                }

                @Override
                public void onDrawFrame(GL10 gl10) {
                    frameBuffer.clear();
                    final float maxDistance = 105f;
                    if(!offset){
                        if(Math.cos(world.getFrameCounter() * 0.03f)<0.0f){
                            plane3.setVisibility(false);
                            plane2.setVisibility(false);
                            plane1.setVisibility(false);
                            mergeObj.setVisibility(true);
                            master.setVisibility(true);
                        }else{
                            plane3.setVisibility(true);
                            plane2.setVisibility(true);
                            plane1.setVisibility(true);
                            mergeObj.setVisibility(false);
                            master.setVisibility(false);
                        }
                    }
                    camera.setPosition(-(0.5f * ((float) Math.abs(Math.cos(world.getFrameCounter() * 0.03f))) + 0.25f) * maxDistance, 30f, 0f);
                    camera.lookAt(new SimpleVector(0, 6f, 0f));
                    world.renderScene(frameBuffer);
                    world.draw(frameBuffer);
                    frameBuffer.display();
                }
            };

            // Attach to some GLSurfaceView...
            viewer.setRenderer(testRenderer);
Title: Re: Lighting on merged Object3Ds
Post by: EgonOlsen on January 04, 2022, 05:53:44 pm
I made myself a test case from your example. On a Samsung S7, there's no issue. The lighting is consistent whether the merged object is visible or the unmerged ones are. On an old LG G4, I can see the issue, though. I'll have a look...
Title: Re: Lighting on merged Object3Ds
Post by: EgonOlsen on January 04, 2022, 08:48:28 pm
Ok, it's cleary some kind of shader bug (...edit: or maybe not...see post below...). Not in the shader code itself but in the shader compiler of some devices. Or in the GPU...I don't know...

Here's what it does (that's not the exact same code that's used by the engine, but it has the same issue):

Code: [Select]
vec3 specPart = specularColors * pow(max(0.0, dot(normalize(-vertexPos.xyz), reflect(-surface2Light, normalEye))), shininess);
vertexColor += vec4((diffuseColors * angle + specPart)*(1.0/(1.0+length(lightPositions - vertexPos.xyz)*attenuation)), 1);

As you can see, it calculates a vertex' color. For this, it also takes the specular color into account. If there is none (i.e. specular on the object is off, which is the default), shininess is 1 and specularColors is vec3(0.0, 0.0, 0.0), i.e. zeroed out. A zero vector multiplied by some value (in this case the result of the pow()-calculation) should be...a zero vector. Because, as we all know, 0 times something is still 0. Turns out, that some devices beg to differ.

We can modify the code to make this more clear:

Code: [Select]
vec3 specPart = vec3(0.0, 0.0, 0.0) * pow(max(0.0, dot(normalize(-vertexPos.xyz), reflect(-surface2Light, normalEye))), shininess);
vertexColor += vec4((diffuseColors * angle + specPart)*(1.0/(1.0+length(lightPositions - vertexPos.xyz) * attenuation)), 1);

Here, specularColors is gone and has been replaced by a static zero vector. Clearly, specPart has to be a zero vector as well in all cases. But it's not. shininess on the other hand is set to 1. However, it too seems to fluctuate in value as well while the shader is executing, which is actually impossible. It's supposed to stay fixed once the shader is executed for a given mesh, hence the name "uniform". Or maybe it doesn't fluctuate but evaluating it in the shader goes wrong for the same reasons that 0 times something is something else rather than 0.

Anyway, if we do this:

Code: [Select]
vec3 specPart = vec3(0.0, 0.0, 0.0) * pow(max(0.0, dot(normalize(-vertexPos.xyz), reflect(-surface2Light, normalEye))), 1.0);
vertexColor += vec4((diffuseColors * angle + specPart)*(1.0/(1.0+length(lightPositions - vertexPos.xyz)*attenuation)), 1);

i.e. replace shininess with a fixed value (doesn't matter which one, 0,1,10...they all work and give the same results), all of a sudden, 0 times something is 0 again.

However, we can't do that because we need both uniforms in case somebody is acutally using specular lighting. I also tried to split the term into smaller parts, which helped in similar situations in the past, but to no avail.

The fact that the behaviour changes when using a single texture is a red herring IMHO. It also changes/works if you are assigning the red texture to the ball instead of the white one.

I'm not sure what to do here. Are you by any chance already using your own shaders? I that case, we could just cut the specular part (if not used, that is) and call it a day. If not, it might be worth considering to do so.

To be sure: Which device are you using that has this issue? As said, I tried it on a S7 and it works fine. It also works fine in the emulator. I fails on the LG G4.





Title: Re: Lighting on merged Object3Ds
Post by: AeroShark333 on January 06, 2022, 04:02:58 am
To be sure: Which device are you using that has this issue? As said, I tried it on a S7 and it works fine. It also works fine in the emulator. I fails on the LG G4.
The videos I sent before are made from an emulator; but I get the same results on my phone (Samsung Galaxy Note 9)

Ok, it's cleary some kind of shader bug. Not in the shader code itself but in the shader compiler of some devices. Or in the GPU...I don't know...
I went through some debugging myself...
I believe it might not be a shader bug after all (or maybe a solvable one still..?)
It appears as if the shininess value(s) is/are not transferred properly to the merged Object3D for some reason..?  ???

According to my IDE (Android Studio in debugging mode) the shininess value sometimes is 0.0 instead of 1.0
I want to stress the "sometimes" above here... it seems that for the merged Object3D, it is sometimes 0.0 and sometimes 1.0..?
I assume it is for different parts of the merged Object3D that it is sometimes 0.0 and sometimes 1.0

I'm tracking the shininess value from here:
GLES20.java [line 282~284 according to IDE's decompiler]
Code: [Select]
if (newShader.shininessHandle != 0) {
            GLES20.glUniform1f(newShader.shininessHandle, this.shininess);
        }

Expectation:
Expected shininess: 1.0
Expected spec_color: vec3(0.0)
Expected result: 0.0*x^1.0 = 0.0*x = 0.0

Experiment:
Measured shininess: 0.0
(Expected) spec_color: vec3(0.0)
Expected result: 0.0*x^0.0 = 0.0*1.0 = 0.0

A zero vector multiplied by some value (in this case the result of the pow()-calculation) should be...a zero vector. Because, as we all know, 0 times something is still 0. Turns out, that some devices beg to differ.
I would have expected this too even with the shininess that seems to fluctuate...

Clearly, specPart has to be a zero vector as well in all cases. But it's not. shininess on the other hand is set to 1. However, it too seems to fluctuate in value as well while the shader is executing, which is actually impossible. It's supposed to stay fixed once the shader is executed for a given mesh, hence the name "uniform". Or maybe it doesn't fluctuate but evaluating it in the shader goes wrong for the same reasons that 0 times something is something else rather than 0.
specPart should always be a zero vector... There seems to be some kind of shader bug there as I agree with the previous statement (0 times x is 0).
To me, it seems that the GPU/driver/OpenGL does not handle "pow(..., x) with x an uniform/non-constant equal to 0" in a shader well.
Though, it seems that this value of 0 is sort of unintented as shininess should be 1?
Therefore, the bug can be avoided by making sure the Java code doesn't supply a zero value I guess..? Or something...

From the OpenGL ES Shading Language sheet:
https://www.khronos.org/files/opengles_shading_language.pdf
[section 8.2, page 65]
Quote
genType pow (genType x, genType y)
Returns x raised to the y power, i.e., x^y
Results are undefined if x < 0.
Results are undefined if x = 0 and y <= 0.
I believe it might not be a shader bug after all since the shader might deal with "Results are undefined if x = 0 and y <= 0"
Though mathematically 0^0 should exist still...
And when you try pow(0.0, 0.0), it still does the multiplication correctly later and zeroes it out...  :o
But when you try pow(0.0, shininess), it breaks again...
What I think is that pow(0.0, 0.0) evaluates to 1.0 and pow(0.0, shininess) evaluates to 'undefined', although they are basically the same...
I guess the shader becomes unpredictable when dealing with 'undefined' values.
And I guess some devices are able to handle the 0.0 values in pow() well still and don't cause any visual bugs...

Are you by any chance already using your own shaders? I that case, we could just cut the specular part (if not used, that is) and call it a day. If not, it might be worth considering to do so.
I'm not using my own shaders (yet) but I might go that way (probably will be based of default shaders)...

I'm not sure what to do here.
I suggest the following solutions:
1. Make sure that a merged Object3D does not have 0 shininess values
2. Make sure that when the shininess value is altered, the Java code will only allow to pass shininess > 0 values. (excluding 0).
3. Make sure that the GLSL shader code can handle 0 shininess values by setting a minimal value. Replace "shininess" with "max(shininess, 0.00001)"
4. Make sure that the GLSL shader code can handle 0 shininess values by adding an offset. Replace "shininess" with "shininess+0.00001"
5. Make sure that the GLSL shader code can handle the first pow term properly. Replace "max(0.0" with "max(0.00001,"
I believe all these solutions would work but I currently ranked them from best to worse...
Personally, I'd only do both 1 and 2... I guess it is best to 'sanitize' the input variables; rather than to fix it in a later stage...
Title: Re: Lighting on merged Object3Ds
Post by: EgonOlsen on January 06, 2022, 09:03:34 am
Strange that this happens in the emulator as well in your case. It doesn't for me.

Anyhow...

Quote
According to my IDE (Android Studio in debugging mode) the shininess value sometimes is 0.0 instead of 1.0
I want to stress the "sometimes" above here... it seems that for the merged Object3D, it is sometimes 0.0 and sometimes 1.0..?
I assume it is for different parts of the merged Object3D that it is sometimes 0.0 and sometimes 1.0

That's what I noticed as well (but by doing some checks in the shader on the device instead of by using a debugger). In your case, it seems to be 1 for the red part and 0 for the green (or vice versa, but something like that). And I also think that multiplying with an undefined value might cause these problems. However, if I set it to 0 or 1 manually, the problem goes away (at least for me), which is not what I would expect.

But maybe you are right. Maybe I'm setting it wrongly. That would explain why it only happens when using multiple textures, because that would cause the object to be split into several parts and it looks like as if I'm setting it correctly for one part but not for the other. Albeit I'm completely in the dark on why that should happen...I'll look into it some more...
Title: Re: Lighting on merged Object3Ds
Post by: AeroShark333 on January 06, 2022, 10:28:16 am
Thanks for looking into it.

I believe compiler might be smart enough in some cases for the pow(x,y) function:
If you manually set y = 0.0, then the compiler probably gets rid of the pow(x,y) altogether and replaces it with a constant value.
If you set y = shininess, then the compiler cannot get rid of the pow(x,y) evaluation as it's dependent on a non-constant value (which could potentially change during runtime).
I believe the compiler-level pow() evaluation goes well or something, but the runtime-level pow() does not..?
I don't know, I'm not an expert on this but this is what I'm guessing :p
Maybe interesting: https://www.shadertoy.com/view/slKSWc

Little late but best wishes for the New Year! :)
Title: Re: Lighting on merged Object3Ds
Post by: EgonOlsen on January 06, 2022, 03:07:06 pm
Happy new year to you as well.

I had a look and I think that I've identified the issue. Can you please give this jar a try: https://jpct.de/download/beta/jpct_ae.jar (https://jpct.de/download/beta/jpct_ae.jar) ?
Title: Re: Lighting on merged Object3Ds
Post by: AeroShark333 on January 09, 2022, 01:57:47 pm
Happy new year to you as well.

I had a look and I think that I've identified the issue. Can you please give this jar a try: https://jpct.de/download/beta/jpct_ae.jar (https://jpct.de/download/beta/jpct_ae.jar) ?
Works like a charm! :D

It fixed both the test case and the original rendering bug.
Thanks for the support (as always) :)
Title: Re: Lighting on merged Object3Ds
Post by: EgonOlsen on January 09, 2022, 02:43:44 pm
Good to hear. This flaw was in there since the very first version of jPCT-AE. Strange that nobody ever noticed it before. I guess it has been mitigated by the fact that it only affects some devices and that you have to use Object3Ds which are using more than one texture combination, which isn't a common use case when you are loading your objects from a file.