-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Closed
Labels
category - custom shaderscategory - graphicsneeds feedbackOn hold until additional info is suppliedOn hold until additional info is suppliedtype - bug
Description
What happened?
it may be a bug on cesium instance attribute.I passed a spatialIndex vertex attribute as an instance attribute to the vertex shader. This attribute was used as a texture index to obtain the vertex coordinates. I found that replacing the index with gl_instanceID could render normally on mobile devices.it seems to turn out that the uint function cannot perform in cesium on mobile phone.even if i use many differerent cesium version
below is my code:
Reproduction steps
var SPECTOR = require("spectorjs");
var spector = new SPECTOR.Spector();
spector.displayUI();
var CesiumViewer;
var gsPrimitiveCollection = [];
// 6*4 + 4 + 4 = 8*4
// XYZ - Position (Float32)
// XYZ - Scale (Float32)
// RGBA - colors (uint8)
// IJKL - quaternion/rot (uint8)
const rowLength = 3 * 4 + 3 * 4 + 4 + 4;
function generateTexture (buffer, vertexCount) {
if (!buffer) return;
const f_buffer = new Float32Array(buffer);
let texwidth = 1024 * 1;
let texheight = Math.ceil((1 * vertexCount) / texwidth);
// 4 components per pixel (RGBA)
let texdata = new Uint32Array(texwidth * texheight * 4);
//let texdata_c = new Uint8Array(texdata.buffer);
let texdata_f = new Float32Array(texdata.buffer);
for (let i = 0; i < vertexCount; i++) {
// x, y, z
texdata_f[12 * i + 0] = f_buffer[8 * i + 0];
texdata_f[12 * i + 1] = f_buffer[8 * i + 1];
texdata_f[12 * i + 2] = f_buffer[8 * i + 2];
}
return {
// texdata:texdata,
texdata: texdata_f,
texwidth: texwidth,
texheight: texheight
}
}
// abstract primitive to hook into render pipe
class CustomPrimitive {
constructor(options) {
this.uniformMap = options.uniformMap;
this.vertexShaderSource = options.vertexShaderSource;
this.fragmentShaderSource = options.fragmentShaderSource;
this.renderState = options.renderState;
this.modelMatrix = options.modelMatrix;
this.instanceCount = options.instanceCount;
// 传过来后在叠加pick color vbo
this.vertexAttributes = options.vertexAttributes
this.vertexArray = options.vertexArray;
this.context = options.context
//this.framebuffer = options.framebuffer;
this.show = true;
this.commandToExecute = undefined;
this.depthPass = undefined;
this.texdata = options.texdata;
this.center = options.center || [0, 0];
this.colorVertextBuffer = undefined
this.pickIdColors = []
this.minmax = options.minmax
var centerCartension = Cesium.Cartesian3.fromDegrees(
this.center[0],
this.center[1],
0,
CesiumViewer.scene.globe.ellipsoid
);
this.boundingSphere = new Cesium.BoundingSphere(centerCartension, 10000);
var _this = this
this.vertexArray = this.createVertextArray(this.vertexAttributes, this.context)
}
createVertextArray (attributes, context) {
const splatsVertexArray = new Cesium.VertexArray({
context: context,
attributes: attributes,
});
return splatsVertexArray
}
createCommand (context) {
var shaderProgram = Cesium.ShaderProgram.fromCache({
context: context,
attributeLocations: this.vertexArray.attributes,
vertexShaderSource: this.vertexShaderSource,
fragmentShaderSource: this.fragmentShaderSource,
debugShaders: true,
logShaderCompilation: true
});
var cachedRenderState = Cesium.RenderState.fromCache(this.renderState);
return new Cesium.DrawCommand({
owner: this,
vertexArray: this.vertexArray,
primitiveType: Cesium.PrimitiveType.POINTS, //Cesium.PrimitiveType.TRIANGLE,////origial
uniformMap: this.uniformMap,
modelMatrix: this.modelMatrix,
instanceCount: this.instanceCount,
shaderProgram: shaderProgram,
//framebuffer: this.framebuffer,
renderState: cachedRenderState,
// pass: Cesium.Pass.TRANSLUCENT,
// pickId:"czm_pickColor",
pass: Cesium.Pass.OPAQUE,
boundingVolume: this.boundingSphere
});
}
update (frameState) {
if (!this.show) {
return;
}
if (!Cesium.defined(this.commandToExecute)) {
this.commandToExecute = this.createCommand(frameState.context);
}
frameState.commandList.push(this.commandToExecute);
// frameState.commandList.push(this.depthPass);
}
isDestroyed () {
return false;
}
destroy () {
if (Cesium.defined(this.commandToExecute)) {
this.commandToExecute.shaderProgram =
this.commandToExecute.shaderProgram &&
this.commandToExecute.shaderProgram.destroy();
}
return Cesium.destroyObject(this);
}
}
function computeModelMatrix (splatCenter) {
const center = Cesium.Cartesian3.fromDegrees(
splatCenter[0],
splatCenter[1],
50,
CesiumViewer.scene.globe.ellipsoid
);
let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);
const rotationMatrix = Cesium.Matrix4.fromRotationTranslation(
Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(-0))
);
modelMatrix = Cesium.Matrix4.multiply(
modelMatrix,
rotationMatrix,
new Cesium.Matrix4()
);
return modelMatrix;
}
function SetupCustomPrimitive (data) {
let InWebGLContext = CesiumViewer.scene.context;
let InPointCount = data.vertexCount;
let texdata = data.texdata;
let splatTexWidth = data.texwidth;
let splatTexHeight = data.texheight;
let center = data.center
let worldMatrix = data.worldMatrix || Cesium.Matrix4.IDENTITY
let minmax = data.bounding
try {
// const triangleVertices = new Float32Array([-2, -2, 2, -2, 2, 2, -2, 2]);
// const triangleVertices = new Float32Array([-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0]);
const triangleVertices = new Float32Array([-1.0, -1.0]);
var triBuffer = Cesium.Buffer.createVertexBuffer({
context: InWebGLContext,
typedArray: triangleVertices,
usage: Cesium.BufferUsage.STATIC_DRAW,
});
var firstIndexDepth = new Float32Array(Math.ceil(InPointCount));
// var intEncodeFloat = (intNumb) => {
// let heih = Math.floor(intNumb / 1024);
// let low = intNumb % 1024;
// return [heih / 255.0, low / 255.0]
// }
for (let i = 0; i < firstIndexDepth.length; i++) {
// let temp = intEncodeFloat(i)
// firstIndexDepth[2 * i] = temp[0];
// firstIndexDepth[2 * i + 1] = temp[1];
firstIndexDepth[i] = i;
}
var orderedSplatIndices = Cesium.Buffer.createVertexBuffer({
context: InWebGLContext,
// typedArray: depthIndex,
typedArray: firstIndexDepth,
usage: Cesium.BufferUsage.STATIC_DRAW,
});
const tempTexture = new Cesium.Texture({
context: InWebGLContext,
width: splatTexWidth,
height: splatTexHeight,
pixelFormat: Cesium.PixelFormat.RGBA,
pixelDatatype: Cesium.PixelDatatype.FLOAT,
source: {
width: splatTexWidth,
height: splatTexHeight,
arrayBufferView: texdata,
},
flipY: false,
sampler: new Cesium.Sampler({
wrapS: Cesium.TextureWrap.CLAMP_TO_EDGE,
wrapT: Cesium.TextureWrap.CLAMP_TO_EDGE,
minificationFilter: Cesium.TextureMinificationFilter.NEAREST,
magnificationFilter: Cesium.TextureMagnificationFilter.NEAREST,
}),
});
let uniformMap = {
u_texture: function () {
return tempTexture;
}
};
const attributes = [
{
index: 0,
enabled: true,
vertexBuffer: triBuffer,
componentsPerAttribute: 2,
componentDatatype: Cesium.ComponentDatatype.FLOAT,
normalize: false,
offsetInBytes: 0,
strideInBytes: 0,
instanceDivisor: 0,
},
{
index: 1,
enabled: true,
vertexBuffer: orderedSplatIndices,
componentsPerAttribute: 1,
componentDatatype: Cesium.ComponentDatatype.FLOAT,
normalize: false,
offsetInBytes: 0,
strideInBytes: 0,
instanceDivisor: 1,
},
];
let modelMatrix = computeModelMatrix(center);
//j雅可比矩阵跟threejs不对应----624行
let vertexShaderSource = `
#version 300 es
#ifdef GL_ES
precision highp float;
precision mediump int;
#endif
uniform sampler2D u_texture;
in vec2 position;
in float spatialIndex;
void main () {
uint stride = 1u;
vec4 cen = texelFetch(u_texture, ivec2((stride * (uint(spatialIndex) & 0x3ffu)), uint(spatialIndex) >> 10), 0);
vec4 cam = czm_modelView * vec4(cen.xyz, 1);
vec4 pos2d = czm_projection * cam;
gl_PointSize = 10.0;
gl_Position = pos2d / pos2d.w;
// uint rowStride= 1023u;
// uint colStride= 10u;
// float colWith = 1024.0;
// float heightWith = 45.0;
// float colnum = mod(spatialIndex,colWith) /(colWith-1.0);
// float rownum = 1.0 - ceil(spatialIndex / colWith)/heightWith;
// vec4 cen = texture(u_texture,vec2(colnum, rownum));
// vec4 cam = czm_modelView * vec4(cen.xyz, 1);
// vec4 pos2d = czm_projection * cam;
}
`.trim();
let fragmentShaderSource = `
#version 300 es
precision highp float;
precision highp int;
void main () {
out_FragColor = vec4(1.0,0.0,0.0, 1.0);
}
`.trim();
let splatRenderState = {
blending: {
enabled: true,
equationRgb: Cesium.BlendEquation.ADD,
//equationAlpha: Cesium.BlendEquation.SUBTRACT,
equationAlpha: Cesium.BlendEquation.ADD,
functionSourceRgb: Cesium.BlendFunction.ONE,
functionSourceAlpha: Cesium.BlendFunction.ONE,
functionDestinationRgb: Cesium.BlendFunction.ONE_MINUS_SOURCE_ALPHA,
functionDestinationAlpha: Cesium.BlendFunction.ONE,
},
depthTest: {
enabled: false,
},
depthMask: false,
cull: {
enabled: true,
face: Cesium.CullFace.FRONT,
},
};
let vertexSource = new Cesium.ShaderSource({
sources: [vertexShaderSource],
});
let fragmentSource = new Cesium.ShaderSource({
sources: [fragmentShaderSource],
});
var customPrimitive = new CustomPrimitive({
vertexAttributes: attributes,
context: InWebGLContext,
uniformMap: uniformMap,
center: center,
modelMatrix: modelMatrix,
vertexShaderSource: vertexSource,
fragmentShaderSource: fragmentSource,
renderState: splatRenderState,
instanceCount: InPointCount,
texdata: texdata,
minmax: minmax
});
return CesiumViewer.scene.primitives.add(customPrimitive);
} catch (err) {
throw err
}
}
async function RenderSplat (viewer, center, splatUrl, filenameWithExt) {
CesiumViewer = viewer
// splatCenter = center
// vue.$message.error(splatUrl)
const url = new URL(splatUrl);
var req
try {
req = await fetch(url, {
mode: "cors", // no-cors, *cors, same-origin
credentials: "omit", // include, *same-origin, omit
})
if (req.status != 200) {
throw new Error(req.status + " Unable to load " + req.url)
}
} catch (error) {
// vue.$message.error(error)
return error
}
const rowLength = 3 * 4 + 3 * 4 + 4 + 4;
const reader = req.body.getReader();
const fileSize = req.headers.get("content-length")
var splatData, vertexCount;
const fileType = filenameWithExt.substr(filenameWithExt.lastIndexOf(".") + 1)
const splatname = filenameWithExt.substr(0, filenameWithExt.lastIndexOf("."))
console.log(fileType);
if (fileType == "splat") {
splatData = new Uint8Array(fileSize);
let bytesRead = 0;
let stopLoading = false;
//worker发送消息
while (true) {
const { done, value } = await reader.read();
if (done) break;
splatData.set(value, bytesRead);
bytesRead += value.length;
}
vertexCount = Math.floor(bytesRead / rowLength)
}
try {
let textureInfo = generateTexture(splatData.buffer, vertexCount)
// 释放文件内存
splatData = null;
var primitiveInfo = {
vertexCount: vertexCount,
...textureInfo,
center: center
};
let primitive = SetupCustomPrimitive(primitiveInfo);
primitive.customId = splatname
gsPrimitiveCollection.push(primitive)
} catch (error) {
return error
}
CesiumViewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(center[0], center[1], 100),
duration: 0.5,
orientation: {
heading: Cesium.Math.toRadians(30.0),
pitch: Cesium.Math.toRadians(-90),
roll: 0.0,
}
});
return {
gsPrimitives: gsPrimitiveCollection
}
}
export default RenderSplatSandcastle example
No response
Environment
Browser:
CesiumJS Version:
Operating System:
Metadata
Metadata
Assignees
Labels
category - custom shaderscategory - graphicsneeds feedbackOn hold until additional info is suppliedOn hold until additional info is suppliedtype - bug