GearVRf icon indicating copy to clipboard operation
GearVRf copied to clipboard

Shader type is always invalid

Open ragner opened this issue 7 years ago • 3 comments

What is the right way to identify the shader type of a material? The following code is always logging INVALID SHADER

        GVRMaterial material = new GVRMaterial(context, GVRMaterial.GVRShaderType.Phong.ID);

        if (material.getShaderType() != GVRMaterial.GVRShaderType.Phong.ID) {
            Log.w("SHADER ERR", "INVALID SHADER: " + material.getShaderType());
        }

ragner avatar Jan 26 '18 15:01 ragner

Looks like in the current version, the shaderId supplied to GVRMaterial constructor is no longer simply kept as a member but gets sent to GVRShaderData's contructor and to GVRShaderManager: https://github.com/Samsung/GearVRf/blob/6c3fd322deb7c6c2ff333b4ef992e78b0b932fa0/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRShaderData.java

If it's copied during the process, then that explains what you observe.

bohuang3d avatar Jan 26 '18 19:01 bohuang3d

I wanted to create a function to verify a scene object had the expected shader type, but couldn't work out a way to do this without using reflection. As this was just a debug feature I didn't think it worth raising as an issue, but if yours is a legitimate use case then the ID field of GVRShaderId will need to made publicly accessible, or a utility function within GVRShaderId added to do the check for you.

This is what I came up with to do the compare.

    public static void assertEquals(GVRShaderId shader1, GVRShaderId shader2) {
        try {
            Field idField = GVRShaderId.class.getDeclaredField("ID");
            idField.setAccessible(true);
            Object id1 = idField.get(shader1);
            Object id2 = idField.get(shader2);
            if (!id1.equals(id2)) {
                String error = "Error wrong shader type, expecting: " + id1 + ", Found: " + id2;
                Log.e(TAG, error);
                throw new RuntimeException(error);
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

SteveGreatApe avatar Jan 29 '18 15:01 SteveGreatApe

The GVRShaderManager maintains a list of all of the shaders. Even if you pass your own GVRShaderId to the GVRMaterial constructor, it still uses the shader manager to retrieve the GVRShaderId so they will always match if it is the same shader. It is the actual shader Java class that is used as the key. You can do this to determine if two shaders are the same at the Java level: GVRShaderId shader1 = object1.getRenderData().getMaterial().getShaderType(); GVRShaderId shader2 = object2.getRenderData().getMaterial().getShaderType();

if (shader1.getTemplate(gvrContext).getClass().equals(shader2.getTemplate(gvrContext).getClass())) { // shaders are the same at the Java level }

NolaDonato avatar Jan 30 '18 22:01 NolaDonato