How to use texture ST coordinate outside interval [0, 1]

Hello!
I have some visual problem when use manually calculated texture coordinates outside interval [0, 1].
By some reason I don’t use “Image” material with repeat uniform.
I create manually wall geometry with 4 points and 2 triangles and self calculate texture coordinates outside interval [0, 1] (use Cesium 1.91 release).

  • Code for position geometry attribute is:
    var geoLine = new Cesium.EllipsoidGeodesic(
    Cesium.Cartographic.fromDegrees(45, 45, 0),
    Cesium.Cartographic.fromDegrees(46, 46, 0),
    )
    var height = 5;
    var distance = 50;
    var gp0 = geoLine.interpolateUsingSurfaceDistance(0);
    var gp1 = new Cesium.Cartographic(gp0.longitude, gp0.latitude, height);
    var gp2 = geoLine.interpolateUsingSurfaceDistance(distance);
    var gp3 = new Cesium.Cartographic(gp2.longitude, gp2.latitude, height);
    var geocentricPositions = [Cesium.Cartographic.toCartesian(gp0),Cesium.Cartographic.toCartesian(gp1),Cesium.Cartographic.toCartesian(gp2),Cesium.Cartographic.toCartesian(gp3)];
    var valuesPosition = new Float64Array(geocentricPositions.length * 3);
    for (var i = 0; i < geocentricPositions.length; i++) {
    valuesPosition[3 * i] = geocentricPositions[i].x;
    valuesPosition[3 * i + 1] = geocentricPositions[i].y;
    valuesPosition[3 * i + 2] = geocentricPositions[i].z;
    }
    var positionAtt = new Cesium.GeometryAttribute({
    componentDatatype: Cesium.ComponentDatatype.DOUBLE,
    componentsPerAttribute: 3,
    values: valuesPosition
    });

  • Code for texture coordinate geometry attribute is:
    var stHeight = 2.2;
    var stWidth = 20.1;
    // var stHeight = 1.0;
    // var stWidth = 1.0;
    var stAtt = new Cesium.GeometryAttribute({
    componentDatatype: Cesium.ComponentDatatype.FLOAT,
    componentsPerAttribute: 2,
    values: new Float32Array([
    0.0, 0.0,
    0.0, stHeight,
    stWidth, 0.0,
    stWidth, stHeight
    ]),
    });

  • Code for create geometry is:
    var boundingSphere = Cesium.BoundingSphere.fromPoints(geocentricPositions);
    var geometry = new Cesium.Geometry({
    attributes: {
    position: positionAtt,
    st: stAtt
    },
    primitiveType: Cesium.PrimitiveType.TRIANGLES,
    indices: new Uint16Array([
    0, 3, 1,
    2, 3, 0
    ]),
    boundingSphere: boundingSphere,
    });
    geometry = Cesium.GeometryPipeline.computeNormal(geometry);
    geometry = Cesium.GeometryPipeline.compressVertices(geometry);

  • Code fore use Cesium.Material like this:
    var material = new Cesium.Material({
    fabric: {
    type: “Image”,
    uniforms: {
    image: “MyScripts/mesh.png”,
    repeat: new Cesium.Cartesian2(1.0, 1.0),
    }
    },
    });

  • And code for create primitive and use it:
    var primitive = new Cesium.Primitive({
    asynchronous: false,
    geometryInstances: new Cesium.GeometryInstance({
    geometry: geometry,
    id: “MyMesh”
    }),
    appearance: new Cesium.MaterialAppearance({
    translucent: false,
    materialSupport: Cesium.MaterialAppearance.MaterialSupport.TEXTURED,
    material: material,
    })
    });
    var labels = new Cesium.LabelCollection();
    labels.add({ position: geocentricPositions[0], text: “№0” });
    labels.add({ position: geocentricPositions[1], text: “№1” });
    labels.add({ position: geocentricPositions[2], text: “№2” });
    labels.add({ position: geocentricPositions[3], text: “№3” });
    viewer.scene.primitives.add(primitive);
    viewer.scene.primitives.add(labels);
    // fly to primitive
    viewer.scene.camera.flyToBoundingSphere(boundingSphere);
    viewer.scene.requestRender();

  • I use self image *.png for texture (32 by 32 pixels)
    image

  • Result (correct) view with Cesium “Image” for parameters (var stHeight and var stWidth use as parameter for texture coordinates):

  1. stHeight = 1.0;
  2. stWidth = 1.0;
  3. fabric “Image” uniform is repeat: new Cesium.Cartesian2(20.1, 2.3).

    This is correct view!
  • Result view with Cesium “Image” for parameters (no repeat, self texture coordinates,
    var stHeight and var stWidth use as parameter for texture coordinates):
  1. stHeight = 2.5;
  2. stWidth = 20.1;
  3. fabric “Image” uniform is repeat: new Cesium.Cartesian2(1.0, 1.0).

    Correct count repeat by width, but height has some visual error.
  • I create self material “ImageTest” by this code:
    if (!Cesium.defined(Cesium.Material.ImageTestType)) {
    Cesium.Material.ImageTestType = “ImageTest”;
    Cesium.Material._materialCache.addMaterial(Cesium.Material.ImageTestType, {
    fabric: {
    type: Cesium.Material.ImageTestType,
    uniforms: {
    image: Cesium.Material.DefaultImageId,
    color: new Cesium.Color(1.0, 1.0, 1.0, 1.0),
    },
    components: {
    // diffuse: “texture2D(image, materialInput.st).rgb * color.rgb”,
    // alpha: “texture2D(image, materialInput.st).a * color.a”,
    diffuse: “texture2D(image, fract(materialInput.st)).rgb * color.rgb”,
    alpha: “texture2D(image, fract(materialInput.st)).a * color.a”,
    },
    },
    translucent: function(material) {
    return material.uniforms.color.alpha < 1.0;
    },
    });

    And try use different parameters for components: diffuse and alpha. Use texture2D(image, materialInput.st) without fract and with it texture2D(image, fract(materialInput.st)).
  • Result view with my"ImageTest" for parameters (self texture coordinates and fract):
  1. stHeight = 2.5;
  2. stWidth = 20.1;
  3. texture2D(image, fract(materialInput.st)).
  • Result view with my"ImageTest" for parameters (self texture coordinates without fract):
  1. stHeight = 2.5;
  2. stWidth = 20.1;
  3. texture2D(image, materialInput.st).

Then I try use parameter for texture Cesium.TextureWrap.REPEAT because
by default fore Cesium Material use Cesium.TextureWrap.CLAMP_TO_EDGE.

I patch Material.js like this (add options for wrapS and wrapT) and build Cesium:

this._magnificationFilter = defaultValue(
options.magnificationFilter,
TextureMagnificationFilter.LINEAR
);
// !!! append use new parameters wrapS and wrapT
this._wrapS = defaultValue(
options.wrapS,
TextureWrap.CLAMP_TO_EDGE
);
this._wrapT = defaultValue(
options.wrapT,
TextureWrap.CLAMP_TO_EDGE
);
//…
const sampler = new Sampler({
minificationFilter: this._minificationFilter,
magnificationFilter: this._magnificationFilter,
//!!! append using wrapS and wrapT
wrapS: this._wrapS,
wrapT: this._wrapT,
});
// and for all operation “new Sampler(…)” in code “Material.js”

I append options (wrapS and wrapT) for Cesium.Material but this not solve my problem (I have patch code but don’t print it).

I could not get result like Cesium “Image” and repeat uniform when i using self “ImageTest” and texture coordinates outside interval [0, 1]. What is incorrect in using Material and st coordinates.

Create Sandcastle examples (modified example, with rectangle wall height and width by 50 meters)

  1. “Example 1-0” - use repeate, st inside [0,1], fabricType “Image”.
  2. “Example 1-1” - st inside [0,1], fabricType “ImageTest”.
  3. “Example 2-0” - st outside [0,1] (s=t=5.1), fabricType “Image”, no repeate.
  4. “Example 2-1” - st outside [0,1] (s=t=5.1), fabricType “ImageTest”, repeate not use.
  5. “Example 2-2” - st outside [0,1] (s=t=5.1), fabricType “ImageTestFract”, repeate not use.
  6. “Example 3-0” - st outside [0,1] (s=t=5.7), fabricType “Image”.
  7. “Example 3-1” - st outside [0,1] (s=t=5.7), fabricType “ImageTest”, repeate not use.
  8. “Example 3-2” - st outside [0,1] (s=t=5.7), fabricType “ImageTestFract”, repeate not use.