A question about Primitive render to texture

hi!!
I found a way to render to texture,but this demo not working in version 1.86.
I try to run this demo,I got a black screen.

1 Like

I trapped in this problem a week,I need help.

@linsanda

Welcome to the community! :rocket: :grinning: I apologize for the delayed response - I was at GEOINT all of last week.

I am also having trouble running the sandcastle demo that you shared. Have you tried copying the code and running it on a local build?

-Sam

I have tried it on local build,but it still doesn’t work.
--------------------------------update-----------------------------
I try to create a custom primitive,and set Framebuffer,which took effect. but It seems not clear previous frame.I dont know how to clear.(my english is not very good. I hope I can express it clearly)

------------------------------------------------update-------------------------------------
GIF 2021-10-12 11-08-20
look function update() .
class MyPrimitive{

constructor(modelMatrix,context,framebuffer){

    this.framebuffer = framebuffer

    var v0 = [0.5, 0.5, 0];

    var v1 = [-0.5, 0.5, 0];

    var v2 = [-0.5, -0.5, 0];

    var v3 = [0.5, -0.5, 0];

    var vertex = [

        ...v0, ...v1, ...v2, ...v3

    ]

    var positions = new Float64Array(vertex)

    var nny = [0,-1,0]

    var normals = new Float32Array([

        ...nny, ...nny, ...nny, ...nny

    ])

    var sts = new Float32Array([

        1.,1.,

        0.,1.,

        0.,0.,

        1.,0.

    ])

    var indices = new Uint16Array([

        0,1,2,0,2,3

    ])

    //纹理

    var texture = undefined

    var imageUri = 'http://localhost:8080/Widgets/Images/ImageryProviders/bingAerial.png'

    Cesium.Resource.createIfNeeded(imageUri).fetchImage().then(function(image){

        console.log('图片已加载')

        var textureObj;

        if(Cesium.defined(image.internalFormat)){

            textureObj = new Cesium.Texture({

                context:context,

                pixelFormat: image.internalFormat,

                width: image.width,

                height: image.height,

                source: {

                    arrayBufferView: image.bufferView

                }

            })

        }else{

            textureObj = new Cesium.Texture({

                context:context,

                source:image

            })

        }

        texture = textureObj

    })

    // 1.6 定义attributeLocations

    var attributeLocations = {

        position: 0,

        normal: 1,

        textureCoordinates: 2,

    };

    var vs  = `

    attribute vec3 position;

    attribute vec3 normal;

    attribute vec2 st;

    attribute float batchId;

    varying vec3 v_positionEC;

    varying vec3 v_normalEC;

    varying vec2 v_st;

    void main(){

        v_positionEC = (czm_modelView * vec4(position, 1.0)).xyz;

        v_normalEC = czm_normal * normal;

        v_st = st;

        gl_Position = czm_modelViewProjection * vec4(position, 1.0);

    }

    `

    var fs = `

    varying vec3 v_positionEC;

    varying vec3 v_normalEC;

    varying vec2 v_st;

    uniform sampler2D myImage;

    void main(){

        vec3 positionToEyeEC = -v_positionEC;

        vec3 normalEC = normalize(v_normalEC);

        #ifdef FACE_FORWARD

            normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);

        #endif

        czm_materialInput materialInput;

        materialInput.normalEC = normalEC;

        materialInput.positionToEyeEC = positionToEyeEC;

        materialInput.st = v_st;

        //An czm_material with default values.

        //Every material's czm_getMaterial should use this default material as a base for the material it returns.

        //The default normal value is given by materialInput.normalEC.

        czm_material material = czm_getDefaultMaterial(materialInput);

        material.diffuse = texture2D(myImage, materialInput.st).rgb;

        // #ifdef FLAT

            gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);

        // #else

        //     gl_FragColor = czm_phong(normalize(positionToEyeEC), material);

        // #endif

    }

    `

    //创建vertexArray(Geometry)

    function createVertexArray(context){

        var geometry = new Cesium.Geometry({

            attributes: {

                position: new Cesium.GeometryAttribute({

                    // vtxf 使用double类型的position进行计算

                    // componentDatatype : Cesium.ComponentDatatype.DOUBLE,

                    componentDatatype: Cesium.ComponentDatatype.FLOAT,

                    componentsPerAttribute: 3,

                    values: positions

                }),

                normal: new Cesium.GeometryAttribute({

                    componentDatatype: Cesium.ComponentDatatype.FLOAT,

                    componentsPerAttribute: 3,

                    values: normals

                }),

                textureCoordinates: new Cesium.GeometryAttribute({

                    componentDatatype: Cesium.ComponentDatatype.FLOAT,

                    componentsPerAttribute: 2,

                    values: sts

                })

            },

            // Workaround Internet Explorer 11.0.8 lack of TRIANGLE_FAN

            indices: indices,

            primitiveType: Cesium.PrimitiveType.TRIANGLES,

            boundingSphere: Cesium.BoundingSphere.fromVertices(positions)

        });

        var vertexArray = Cesium.VertexArray.fromGeometry({

            context: context,

            geometry: geometry,

            attributeLocations: attributeLocations,

            bufferUsage: Cesium.BufferUsage.STATIC_DRAW,

            // interleave : true

        });

        return vertexArray;

    }

    //创建command

    function createCommand(context){

        var translucent = false

        var closed = true

        // 借用一下Appearance.getDefaultRenderState

        var rawRenderState = Cesium.Appearance.getDefaultRenderState(translucent, closed, undefined);

        var renderState = Cesium.RenderState.fromCache(rawRenderState);

        var vertexShaderSource = new Cesium.ShaderSource({

            sources: [vs]

        });

        var fragmentShaderSource = new Cesium.ShaderSource({

            sources: [fs]

        });

        var uniformMap = {

            myImage: function() {

                if (Cesium.defined(texture)) {

                    return texture;

                } else {

                    return context.defaultTexture;

                }

            }

        }

        var shaderProgram = Cesium.ShaderProgram.fromCache({

            context: context,

            vertexShaderSource: vertexShaderSource,

            fragmentShaderSource: fragmentShaderSource,

            attributeLocations: attributeLocations

        });

        return new Cesium.DrawCommand({

            vertexArray: createVertexArray(context),

            primitiveType: Cesium.PrimitiveType.TRIANGLES,

            renderState: renderState,

            shaderProgram: shaderProgram,

            uniformMap: uniformMap,

            owner: this,

            framebuffer : framebuffer?framebuffer:undefined,

            pass: Cesium.Pass.OPAQUE,

            modelMatrix: modelMatrix,

        })

    }

    //清空命令

    function createClearCommand(fb){

        // var c = Cesium.ClearCommand.ALL

        return new Cesium.ClearCommand({

            pass:Cesium.Pass.OPAQUE,

            framebuffer:this.framebuffer,

            color:new Cesium.Color(0.,0.,0.,0.),

        })

    }

    this.show = true

    this._command = undefined

    this._createCommand = createCommand;

    this._cCommand = undefined

    this._createClearCommand = createClearCommand;

}

update(frameState){

    if(!this.show){

        return

    }

    if(!Cesium.defined(this._cCommand) && this.framebuffer){

        this._cCommand = this._createClearCommand(this.framebuffer)

    }

    if(!Cesium.defined(this._command)){

        this._command = this._createCommand(frameState.context)

    }

   

    if(Cesium.defined(this._cCommand)){

        frameState.commandList.push(this._cCommand)

    }

    if(Cesium.defined(this._command)){

        frameState.commandList.push(this._command)

    }

   

}

isDestroyed() {

    return false;

}

destroy() {

    if (Cesium.defined(this._command)) {

        this._command.shaderProgram = this._command.shaderProgram && this._command.shaderProgram.destroy();

    }

    return destroyObject(this);

}

}
============================update==================================
I think I solved this problem.
GIF 2021-10-12 14-23-09

function createClearCommand(){

        return new Cesium.ClearCommand({

            pass:Cesium.Pass.OPAQUE,

            color:new Cesium.Color(0.,0.,0.,0.),

            framebuffer:this.framebuffer,

            stencil : 0,

            owner : this,

            depth: 1.0,

        })

    }
1 Like

@linsanda

Amazing work! It looks like your most recent update fixed the issue. Please reach out if you have any other questions or concerns.

-Sam

Can you offer me a demo? I have been confused on render to texture for a long time

texture in framebuffer._colorTextures.

class MyPrimitive{
    constructor(modelMatrix,context,framebuffer){
        this.framebuffer = framebuffer
        var v0 = [0.5, 0.5, 0];
        var v1 = [-0.5, 0.5, 0];
        var v2 = [-0.5, -0.5, 0];
        var v3 = [0.5, -0.5, 0];

        var vertex = [
            ...v0, ...v1, ...v2, ...v3
        ]
        var positions = new Float64Array(vertex)

        var nny = [0,-1,0]
        var normals = new Float32Array([
            ...nny, ...nny, ...nny, ...nny
        ])

        var sts = new Float32Array([
            1.,1.,
            0.,1.,
            0.,0.,
            1.,0.
        ])

        var indices = new Uint16Array([
            0,1,2,0,2,3
        ])

        //纹理
        var texture = undefined
        var imageUri = 'http://localhost:8080/Widgets/Images/ImageryProviders/bingAerial.png'
        Cesium.Resource.createIfNeeded(imageUri).fetchImage().then(function(image){
            console.log('图片已加载')
            var textureObj;
            if(Cesium.defined(image.internalFormat)){
                textureObj = new Cesium.Texture({
                    context:context,
                    pixelFormat: image.internalFormat,
                    width: image.width,
                    height: image.height,
                    source: {
                        arrayBufferView: image.bufferView
                    }
                })
            }else{
                textureObj = new Cesium.Texture({
                    context:context,
                    source:image
                })
            }
            texture = textureObj
        })

        // 1.6 定义attributeLocations
        var attributeLocations = {
            position: 0,
            normal: 1,
            textureCoordinates: 2,
        };

        var vs  = `
        attribute vec3 position;
        attribute vec3 normal;
        attribute vec2 st;
        attribute float batchId;

        varying vec3 v_positionEC;
        varying vec3 v_normalEC;
        varying vec2 v_st;

        void main(){
            v_positionEC = (czm_modelView * vec4(position, 1.0)).xyz;
            v_normalEC = czm_normal * normal;
            v_st = st;
            gl_Position = czm_modelViewProjection * vec4(position, 1.0);
        }
        `

        var fs = `
        varying vec3 v_positionEC;
        varying vec3 v_normalEC;
        varying vec2 v_st;
        uniform sampler2D myImage;
        varying vec3 v_normal;
        void main(){
            vec3 positionToEyeEC = -v_positionEC;
            vec3 normalEC = normalize(v_normalEC);
            #ifdef FACE_FORWARD
                normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);
            #endif

            czm_materialInput materialInput;
            materialInput.normalEC = normalEC;
            materialInput.positionToEyeEC = positionToEyeEC;
            materialInput.st = v_st;

            //An czm_material with default values. 
            //Every material's czm_getMaterial should use this default material as a base for the material it returns. 
            //The default normal value is given by materialInput.normalEC.
            czm_material material = czm_getDefaultMaterial(materialInput);
            material.diffuse = texture2D(myImage, materialInput.st).rgb;

            // #ifdef FLAT
                gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);  //vec4(normalEC.xyz,1.);
            // #else
            //     gl_FragColor = czm_phong(normalize(positionToEyeEC), material);
            // #endif
        }
        `
        //创建vertexArray(Geometry)
        function createVertexArray(context){
            var geometry = new Cesium.Geometry({
                attributes: {
                    position: new Cesium.GeometryAttribute({
                        // vtxf 使用double类型的position进行计算
                        // componentDatatype : Cesium.ComponentDatatype.DOUBLE,
                        componentDatatype: Cesium.ComponentDatatype.FLOAT,
                        componentsPerAttribute: 3,
                        values: positions
                    }),
                    normal: new Cesium.GeometryAttribute({
                        componentDatatype: Cesium.ComponentDatatype.FLOAT,
                        componentsPerAttribute: 3,
                        values: normals
                    }),
                    textureCoordinates: new Cesium.GeometryAttribute({
                        componentDatatype: Cesium.ComponentDatatype.FLOAT,
                        componentsPerAttribute: 2,
                        values: sts
                    })
                },
                // Workaround Internet Explorer 11.0.8 lack of TRIANGLE_FAN
                indices: indices,
                primitiveType: Cesium.PrimitiveType.TRIANGLES,
                boundingSphere: Cesium.BoundingSphere.fromVertices(positions)
            });

            var vertexArray = Cesium.VertexArray.fromGeometry({
                context: context,
                geometry: geometry,
                attributeLocations: attributeLocations,
                bufferUsage: Cesium.BufferUsage.STATIC_DRAW,
                // interleave : true
            });

            return vertexArray;
        }

        //创建command
        function createCommand(context){
            var translucent = false
            var closed = true
            // 借用一下Appearance.getDefaultRenderState
            var rawRenderState = Cesium.Appearance.getDefaultRenderState(translucent, closed, undefined);
            var renderState = Cesium.RenderState.fromCache(rawRenderState);

            var vertexShaderSource = new Cesium.ShaderSource({
                sources: [vs]
            });

            var fragmentShaderSource = new Cesium.ShaderSource({
                sources: [fs]
            });

            var uniformMap = {
                myImage: function() {
                    if (Cesium.defined(texture)) {
                        return texture;
                    } else {
                        return context.defaultTexture;
                    }
                }
            }

            var shaderProgram = Cesium.ShaderProgram.fromCache({
                context: context,
                vertexShaderSource: vertexShaderSource,
                fragmentShaderSource: fragmentShaderSource,
                attributeLocations: attributeLocations
            });

            return new Cesium.DrawCommand({
                vertexArray: createVertexArray(context),
                primitiveType: Cesium.PrimitiveType.TRIANGLES,
                renderState: renderState,
                shaderProgram: shaderProgram,
                uniformMap: uniformMap,
                owner: this,
                framebuffer : framebuffer?framebuffer:undefined,
                pass: Cesium.Pass.OPAQUE,
                modelMatrix: modelMatrix,
            })
        }

        //清空命令
        function createClearCommand(fb){
            return new Cesium.ClearCommand({
                pass:Cesium.Pass.OPAQUE,
                color:new Cesium.Color(0.,0.,0.,0.),
                framebuffer:this.framebuffer,
                // stencil : 0,
                // owner : this,
                depth: 1.0,
            })
        }

        this.show = true
        this._command = undefined
        this._createCommand = createCommand;

        this._cCommand = undefined
        this._createClearCommand = createClearCommand;
    }

    update(frameState){
        if(!this.show){
            return
        }
        if(!Cesium.defined(this._cCommand) && this.framebuffer){
            this._cCommand = this._createClearCommand()
        }
        if(Cesium.defined(this._cCommand)){
            frameState.commandList.push(this._cCommand)
        }

        if(!Cesium.defined(this._command)){
            this._command = this._createCommand(frameState.context)
        }
        if(Cesium.defined(this._command)){
            frameState.commandList.push(this._command)
        }
        
    }

    isDestroyed() {
        return false;
    }

    destroy() {
        if (Cesium.defined(this._command)) {
            this._command.shaderProgram = this._command.shaderProgram && this._command.shaderProgram.destroy();
        }
        return destroyObject(this);
    };
}
2 Likes

Thank you, I would try it, merry Christmas!

1 Like

Thank you @linsanda for sharing that code example!

你好!我看了你的代码是有中文注释,我直接用中文提问了,表达更准确些。我最近也在研究把上一个primitive 渲染存到framebuffer里面的texture,然后再把framebuffer里面的colorTexture贴图到下一个primitive,尝试过很多次,不知道如何使用/解决,请问你是如何解决的,可否赐教?

Hello! I saw that your code has Chinese comments. I asked questions directly in Chinese. Recently, I have been studying how to save the last primitive rendering to the texture in the framebuffer, and then map the colortexture in the framebuffer to the next primitive. I have tried many times. I don’t know how to use / solve it. How do you solve it? Can you give me some advice?