Sceneform-android-sdk: Skybox in SceneView

Created on 27 Dec 2018  路  4Comments  路  Source: google-ar/sceneform-android-sdk

Hello,

I am trying to create a skybox in SceneView using external texture but I can't make it work properly.

Based on the official documents here is my skybox material definition

material {
    name : Skybox,
    parameters : [
        {
           type : sampler2d,
           name : skybox
        }
    ],
    variables : [
         eyeDirection
    ],
    vertexDomain : device,
    depthWrite : false,
    shadingModel : unlit
}

fragment {
    void material(inout MaterialInputs material) {
        prepareMaterial(material);
        float theta = acos(variable_eyeDirection.y);
        float phi = atan(variable_eyeDirection.z / variable_eyeDirection.x) +
            (variable_eyeDirection.x > 0.0 ? 0.0 : PI);
        material.baseColor = texture(materialParams_skybox,
            vec2((phi + PI / 2.0) / (2.0 * PI), theta / PI));
    }
}

vertex {
    void materialVertex(inout MaterialVertexInputs material) {
        float3 p = getPosition().xyz;
        float3 u = mulMat4x4Float3(getViewFromClipMatrix(), p).xyz;
        material.eyeDirection.xyz = mulMat3x3Float3(getWorldFromViewMatrix(), u);
    }
}

I used a simple plane as the shape data since the material has device vertex domain.

o Plane
v -1.000000 -1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v 1.000000 1.000000 1.000000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vn 0.0000 0.0000 1.0000
s off
f 1/1/1 2/2/1 4/3/1 3/4/1

Then my texture image is something link this . I am not really sure what kind of texture image to use here.

When I run it. It looks strange. The top and bottom looks distorted and I saw no texture after turning +90 or -90 degree from start.

I am new to this and really need your help.

Thanks

Most helpful comment

The skybox from the documentation is expecting an equirectangular image. There is a bug in the code actually, so this custom material works better:

material {
    name : "Skybox material",
    parameters : [
        {
            type : sampler2d,
            name : skybox
        }
    ],
    variables : [
        eyeDirection
    ],

    shadingModel : unlit,
    depthWrite: false,
    vertexDomain : device,
}

fragment {
    void material(inout MaterialInputs material) {
        prepareMaterial(material);

        vec3 dir = variable_eyeDirection.xyz;
        float len = sqrt(dir.x*dir.x + dir.y * dir.y + dir.z * dir.z);

        float theta = acos(dir.y/len);
        float phi = atan(dir.x, dir.z);
        float x =  0.5 + phi / (PI * 2.0);
        float y =  theta / PI;
        float c = -dir.y/len;

        material.baseColor = texture(materialParams_skybox, vec2(x, y),
            -2.0 * log2 (1.0 + c * c));
    }
}

vertex {
    void materialVertex(inout MaterialVertexInputs material) {
        float3 p = getPosition().xyz;
        float3 u = mulMat4x4Float3(getViewFromClipMatrix(), p).xyz;
        material.eyeDirection.xyz = mulMat3x3Float3(getWorldFromViewMatrix(), u);
    }
}

The .sfa is:

{
   materials: [
      {
         name: "None",
         parameters: [
            {
               skybox: "sky1",
            },

         ],
         source: "sampledata/models/skybox.mat",
      },
   ],
   model: {
      attributes: [
         "Position",
         "TexCoord",
         "Orientation",
      ],
      collision: {},
      file: "sampledata/models/skybox.obj",
      name: "skybox",
   },
   samplers: [
      {
         file: "sampledata/models/360pic.png",
         name: "sky1",
      },
   ],
   version: "0.51:1",
}

The image I tested with is one I took with a 360 degree camera:
360pic

All 4 comments

The skybox from the documentation is expecting an equirectangular image. There is a bug in the code actually, so this custom material works better:

material {
    name : "Skybox material",
    parameters : [
        {
            type : sampler2d,
            name : skybox
        }
    ],
    variables : [
        eyeDirection
    ],

    shadingModel : unlit,
    depthWrite: false,
    vertexDomain : device,
}

fragment {
    void material(inout MaterialInputs material) {
        prepareMaterial(material);

        vec3 dir = variable_eyeDirection.xyz;
        float len = sqrt(dir.x*dir.x + dir.y * dir.y + dir.z * dir.z);

        float theta = acos(dir.y/len);
        float phi = atan(dir.x, dir.z);
        float x =  0.5 + phi / (PI * 2.0);
        float y =  theta / PI;
        float c = -dir.y/len;

        material.baseColor = texture(materialParams_skybox, vec2(x, y),
            -2.0 * log2 (1.0 + c * c));
    }
}

vertex {
    void materialVertex(inout MaterialVertexInputs material) {
        float3 p = getPosition().xyz;
        float3 u = mulMat4x4Float3(getViewFromClipMatrix(), p).xyz;
        material.eyeDirection.xyz = mulMat3x3Float3(getWorldFromViewMatrix(), u);
    }
}

The .sfa is:

{
   materials: [
      {
         name: "None",
         parameters: [
            {
               skybox: "sky1",
            },

         ],
         source: "sampledata/models/skybox.mat",
      },
   ],
   model: {
      attributes: [
         "Position",
         "TexCoord",
         "Orientation",
      ],
      collision: {},
      file: "sampledata/models/skybox.obj",
      name: "skybox",
   },
   samplers: [
      {
         file: "sampledata/models/360pic.png",
         name: "sky1",
      },
   ],
   version: "0.51:1",
}

The image I tested with is one I took with a 360 degree camera:
360pic

Please reopen if you still have issues.

Please reopen if you still have issues.

Can you look at your project code? Or a demo, thank you

Please reopen if you still have issues.

Can you look at your project code? Or a demo, thank you

@chen8888 I was able to get this to work like so

        Texture.builder()
                .setSource(context, R.sky) // this is my .png
                .build()
                .thenAccept { skyBox ->
                    ModelRenderable.builder()
                            .setSource(context, R.raw.sky_box) // this is my .sfb
                            .build()
                            .thenAccept { skyBoxRenderable ->
                                skyBoxRenderable.material.setTexture("skybox", skyBox)
                                scene.addChild(Node().apply { renderable = skyBoxRenderable })
                            }
                }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

dementia2029 picture dementia2029  路  3Comments

yashvv picture yashvv  路  3Comments

scolar picture scolar  路  4Comments

michaelvogt picture michaelvogt  路  4Comments

terezo picture terezo  路  3Comments