I am working on custom render in Cesium and now I can draw something to framebuffer.
I try to draw the framebuffer to screen with its depth information. The color is drawn to the screen but the depth is incorrect.
I know that Cesium uses log depth by default, but I think it is not the cause of my problem because I merely want to copy the depth to the screen.
BTW, when render to the screen directly(set the option framebuffer : undefined) I get correct depth, but I need to
capture the render result for further process, so I have to render to framebuffer
2. A minimal code example. If you've found a bug, this helps us reproduce and repair it.
Here is what I did, I extract the important parts of my code, you can see my complete code in my Github https://github.com/RaymanNg/3D-Wind-Field
1. setup the texture
var createTexture = function (options, typedArray) {
if (Cesium.defined(typedArray)) {
// typed array needs to be passed as source option, this is required by Cesium.Texture
var source = {};
source.arrayBufferView = typedArray;
options.source = source;
}
var texture = new Cesium.Texture(options);
return texture;
}
const dataTextureSampler = new Cesium.Sampler({
// the values of data texture should not be interpolated
minificationFilter: Cesium.TextureMinificationFilter.NEAREST,
magnificationFilter: Cesium.TextureMagnificationFilter.NEAREST
});
const colorTextureOptions = {
context: context,
width: context.drawingBufferWidth,
height: context.drawingBufferHeight,
pixelFormat: Cesium.PixelFormat.RGBA,
pixelDatatype: Cesium.PixelDatatype.UNSIGNED_BYTE,
sampler: dataTextureSampler
}
const depthTextureOptions = {
context: context,
width: context.drawingBufferWidth,
height: context.drawingBufferHeight,
pixelFormat: Cesium.PixelFormat.DEPTH_COMPONENT,
pixelDatatype: Cesium.PixelDatatype.UNSIGNED_SHORT,
sampler: dataTextureSampler
}
colorTexture = createTexture(colorTextureOptions);
depthTexture = createTexture(depthTextureOptions);
2. setup the framebuffer
var createFramebuffer = function (colorTexture, depthTexture) {
var framebuffer = new Cesium.Framebuffer({
context: context,
colorTextures: [colorTexture],
depthTexture: depthTexture
});
return framebuffer;
}
framebuffer = createFramebuffer(colorTexture, depthTexture);
3. setup the drawCommand
var uniformMap = {
screenColor: function () {
return colorTexture;
},
screenDepth: function () {
return depthTexture;
}
};
new Cesium.DrawCommand({
owner: this,
vertexArray: createVertexArray(context),
primitiveType: primitiveType,
uniformMap: uniformMap,
modelMatrix: Cesium.Matrix4.IDENTITY,
shaderProgram: shaderProgram,
framebuffer: framebuffer,
renderState: renderState,
pass: Cesium.Pass.OPAQUE
});
4. the glsl code
frag shader:
uniform sampler2D screenColor;
uniform sampler2D screenDepth;
varying vec2 textureCoordinate;
void main() {
vec4 color = texture2D(screenColor, textureCoordinate);
float depth = texture2D(screenDepth, textureCoordinate).r;
gl_FragColor = color;
gl_FragDepthEXT = depth;
}
3. Context. Why do you need to do this? We might know a better way to accomplish your goal.
I want to make a GPU particle system, you can see the full problem context in my previous threads:
https://groups.google.com/forum/#!topic/cesium-dev/gjjd9TNeY2A
https://groups.google.com/forum/#!topic/cesium-dev/7kCcITmGbEA
4. The Cesium version you're using, your operating system and browser.
Cesium 1.53
It seems that Cesium store globeDepthTexture in the UniformState class.
The depth value will be encoded into RGBA unsigned bytes and stored into the globeDepthTexture
After looking into the source code, I think can use the built-in value czm_globeDepthTexture and the method czm_unpackDepth to get the depth value.
But I am not sure it is the right way because I still get incorrect depth in my custom render, maybe it is the problem of my own depth texture?
Anyway, I will continue to locate the problem, and I really hope someone can help me know more about how Cesium handle depth texture. Any help would be appreciated
"float globeDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, textureCoordinate));" is the right way to get the depth value of Cesium.
I just did not write the correct depth value into my own texture.
Finally I am able to do a complete custom render in Cesium