Попытка передать текстуру из кадрового буфера приводит к получению L_INVALID_OPERATION: glDrawArrays: исходная и целевая текстуры рисования совпадают - PullRequest
0 голосов
/ 26 октября 2019

Я новичок в vanilla WebGL и пытаюсь использовать кадровые буферы для постобработки / продвинутых шейдеров. Когда я запускаю свой код, я получаю предупреждение:

GL_INVALID_OPERATION: glDrawArrays: Исходная и целевая текстуры рисования совпадают.

Вот мой код до сих пор. Если кто-нибудь может указать мне правильное направление, как правильно использовать кадровые буферы для передачи текстур к следующему проходу. Он обернут в компонент vue.js, но это не должно иметь значения.

<template lang='pug'>

    canvas

</template>

<script>

import { mapGetters } from 'vuex'

export default {
    name: 'webGl',
    created ()
    {
        this.static = {
            af: null,
            gl: null,
            fr: 0,
            shaders:
            {
                vertex: `
                attribute vec2 a_position;

                void main() {
                    gl_Position = vec4(a_position, 0, 1);
                }`,
                fragment: `
                #ifdef GL_ES
                precision mediump float;
                #endif

                uniform float u_time;
                uniform vec2 u_size;
                uniform int u_frame;
                uniform sampler2D u_texture;

                const int maxIter = 15;

                vec2 getPos() {
                    vec2 pos = ( gl_FragCoord.xy / u_size.xy ) - vec2(0.5);
                    pos.x *= u_size.x / u_size.y;
                    return pos;
                }

                vec2 cmult(vec2 a, vec2 b){
                    return vec2(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
                }

                float length2(vec2 v){
                    return v.x*v.x+v.y*v.y;
                }

                vec2 map(vec2 pos){
                    return pos;
                    return vec2(pos.x * sqrt(1.-pos.y*pos.y*3.), pos.y * sqrt(1.-pos.x*pos.x*2.));
                }

                vec2 iterate(vec2 p, vec2 c){
                    vec2 p2 = cmult(p,p);
                    return p2 + c;
                }

                bool checkAbort(vec2 p, vec2 c){
                    return length2(p) > 400.;
                }

                float l2 = log(2.);

                vec4 defaultColor ( void )
                {
                    return vec4(0.35,0.35,0.35,1.0);
                }

                vec4 color(int iterations, vec2 p){
                    float col = .20 + (float(iterations) - log(log(length2(p)))/l2) / float(maxIter);
                    return defaultColor() * vec4(col);
                }

                void main( void ){
                    if (u_frame < 300)
                    {
                        vec2 c = map(getPos())*0.8 - vec2(0.5);
                        vec2 p = c + vec2(sin(-u_time), cos(u_time)) * 0.2;
                        float m;

                        for(int i = 0; i < maxIter ;i++) {
                            p = iterate(p,c);
                            if(checkAbort(p,c)){
                                gl_FragColor = color(i,p);
                                return;
                            }
                        }
                        gl_FragColor = defaultColor();
                    }
                    else
                    {
                        gl_FragColor = texture2D(u_texture, gl_FragCoord.xy / u_size.xy);
                    }
                }`,
                program: null,
                attributes: {},
                uniforms: {},
                time: 0
            }
        }
    },
    mounted ()
    {
        this.setInitWebGlContext()
        this.setInitShaderProgram()
        this.setInitAttributes(['a_position'])
        this.setInitUniforms(['u_size', 'u_time', 'u_frame', 'u_texture'])
        this.setInitGeometryBuffer()

        this.setRenderLoop()
    },
    beforeDestroy ()
    {
        window.cancelAnimationFrame(this.static.af)
    },
    computed:
    {
        ...mapGetters([
            'getCalcs'
        ])
    },
    methods:
    {
        setInitWebGlContext ()
        {
            this.static.gl = this.$el.getContext('webgl')

            if (this.static.gl === null)
            {
                console.log('Unable to initialize WebGL. Your browser or machine may not support it.')
            }
        },
        setInitShaderProgram ()
        {
            const gl = this.static.gl

            this.static.shaders.program = gl.createProgram()

            const vertexShader = gl.createShader(gl.VERTEX_SHADER)
            const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)

            gl.shaderSource(vertexShader, this.static.shaders.vertex)
            gl.shaderSource(fragmentShader, this.static.shaders.fragment)

            gl.compileShader(vertexShader)
            gl.compileShader(fragmentShader)

            gl.attachShader(this.static.shaders.program, vertexShader)
            gl.attachShader(this.static.shaders.program, fragmentShader)
            gl.linkProgram(this.static.shaders.program)
            gl.useProgram(this.static.shaders.program)
        },
        setInitAttributes (keys)
        {
            const gl = this.static.gl
            const program = this.static.shaders.program

            for (let i = 0; i < keys.length; i++)
            {
                this.static.shaders.attributes[keys[i]] = gl.getAttribLocation(program, keys[i])
            }
        },
        setInitUniforms (keys)
        {
            const gl = this.static.gl
            const program = this.static.shaders.program

            for (let i = 0; i < keys.length; i++)
            {
                this.static.shaders.uniforms[keys[i]] = gl.getUniformLocation(program, keys[i])
            }
        },
        setInitGeometryBuffer ()
        {
            const gl = this.static.gl
            const buffer = gl.createBuffer()

            gl.bindBuffer(this.static.gl.ARRAY_BUFFER, buffer)
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0]), gl.STATIC_DRAW)
        },
        setCreateTexture ()
        {
            const gl = this.static.gl
            const width = this.getCalcs.vw
            const height = this.getCalcs.vh
            const texture = gl.createTexture()

            gl.bindTexture(gl.TEXTURE_2D, texture)
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)

            return texture
        },
        setCreateFramebuffer ()
        {
            const gl = this.static.gl
            const buffer = gl.createFramebuffer()

            gl.bindFramebuffer(gl.FRAMEBUFFER, buffer)

            const texture = this.setCreateTexture()

            gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)

            return {
                texture: texture,
                buffer: buffer
            }
        },
        setRenderLoop ()
        {
            this.static.af = window.requestAnimationFrame(this.setRenderLoop)

            const gl = this.static.gl
            const fb = this.static.fb
            const width = this.getCalcs.vw
            const height = this.getCalcs.vh
            const attributes = this.static.shaders.attributes
            const uniforms = this.static.shaders.uniforms
            const mouse = this.static.shaders.mouse
            const fr = this.static.fr

            this.$el.width = width
            this.$el.height = height

            const bufferA = this.setCreateFramebuffer()

            gl.viewport(0, 0, width, height)
            gl.clearColor(0.0, 0.0, 0.0, 0.0)
            gl.clear(gl.COLOR_BUFFER_BIT)

            gl.enableVertexAttribArray(attributes.a_position)
            gl.vertexAttribPointer(attributes.a_position, 2, gl.FLOAT, false, 0, 0)
            gl.uniform2f(uniforms.u_size, width, height)
            gl.uniform1f(uniforms.u_time, window.performance.now() / 3000)
            gl.uniform1i(uniforms.u_frame, fr)
            gl.drawArrays(gl.TRIANGLES, 0, 6)

            gl.bindTexture(gl.TEXTURE_2D, bufferA.texture)
            gl.bindFramebuffer(gl.FRAMEBUFFER, null)

            gl.viewport(0, 0, width, height)
            gl.clearColor(0.0, 0.0, 0.0, 0.0)
            gl.clear(gl.COLOR_BUFFER_BIT)

            gl.enableVertexAttribArray(attributes.a_position)
            gl.vertexAttribPointer(attributes.a_position, 2, gl.FLOAT, false, 0, 0)
            gl.uniform2f(uniforms.u_size, width, height)
            gl.uniform1f(uniforms.u_time, window.performance.now() / 3000)
            gl.uniform1i(uniforms.u_frame, fr)
            gl.uniform1i(uniforms.u_texture, 0)
            gl.drawArrays(gl.TRIANGLES, 0, 6)

            this.static.fr++
        }
    }
}

</script>

Я сейчас на несколько шагов дальше, этот код ниже теперь работает

<template lang='pug'>

    canvas

</template>

<script>

import { mapGetters } from 'vuex'

import forEach from 'lodash/forEach'

export default {
    name: 'webGl',
    created ()
    {
        this.static = {
            af: null,
            gl: null,
            fr: 0,
            shaders:
            {
                noise:
                {
                    vertex: `
                    attribute vec2 a_position;

                    void main() {
                        gl_Position = vec4(a_position, 0, 1);
                    }`,
                    fragment: `
                    #ifdef GL_ES
                    precision mediump float;
                    #endif

                    uniform vec2 u_size;

                    vec2 hash( vec2 p ) {
                        p = vec2( dot(p,vec2(127.1,311.7)),
                        dot(p,vec2(269.5,183.3)));

                        return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);
                    }

                    float noise( vec2 p ) {

                        const float K1 = 0.366025404;
                        const float K2 = 0.211324865;

                        vec2 i = floor(p + (p.x + p.y) * K1);
                        vec2 a = p - i + (i.x + i.y) * K2;
                        vec2 o = step(a.yx, a.xy);
                        vec2 b = a - o + K2;
                        vec2 c = a - 1.0 + 2.0 * K2;

                        vec3 h = max(0.5 - vec3(dot(a,a), dot(b,b), dot(c,c)), 0.0);

                        vec3 n = h * h * h * h * vec3(dot(a, hash(i + 0.0)), dot(b, hash(i + o)), dot(c, hash(i + 1.0)));

                        return dot(n, vec3(70.0));
                    }

                    void main( void ) {
                        vec2 vUv = gl_FragCoord.xy / u_size.xy;
                        vec3 rnd = vec3(noise(16.0 * vUv + 1.1), noise(16.0 * vUv + 2.2), noise(16.0 * vUv + 3.3));
                        gl_FragColor = vec4(rnd, 1.0);
                    }`,
                    program: null,
                    attributes:
                    {
                        a_position: null
                    },
                    uniforms:
                    {
                        u_size: null
                    }
                },
                fluid:
                {
                    vertex: `
                    attribute vec2 a_position;

                    void main() {
                        gl_Position = vec4(a_position, 0, 1);
                    }`,
                    fragment: `
                    #ifdef GL_ES
                    precision mediump float;
                    #endif

                    uniform vec2 u_size;
                    uniform sampler2D u_image;

                    vec2 normz(vec2 x) {
                        return x == vec2(0.0, 0.0) ? vec2(0.0, 0.0) : normalize(x);
                    }

                    vec3 advect(vec2 ab, vec2 vUv, vec2 step, float sc) {

                        vec2 aUv = vUv - ab * sc * step;

                        const float _G0 = 0.25; // center weight
                        const float _G1 = 0.125; // edge-neighbors
                        const float _G2 = 0.0625; // vertex-neighbors

                        // 3x3 neighborhood coordinates
                        float step_x = step.x;
                        float step_y = step.y;
                        vec2 n  = vec2(0.0, step_y);
                        vec2 ne = vec2(step_x, step_y);
                        vec2 e  = vec2(step_x, 0.0);
                        vec2 se = vec2(step_x, -step_y);
                        vec2 s  = vec2(0.0, -step_y);
                        vec2 sw = vec2(-step_x, -step_y);
                        vec2 w  = vec2(-step_x, 0.0);
                        vec2 nw = vec2(-step_x, step_y);

                        vec3 uv =    texture2D(u_image, fract(aUv)).xyz;
                        vec3 uv_n =  texture2D(u_image, fract(aUv+n)).xyz;
                        vec3 uv_e =  texture2D(u_image, fract(aUv+e)).xyz;
                        vec3 uv_s =  texture2D(u_image, fract(aUv+s)).xyz;
                        vec3 uv_w =  texture2D(u_image, fract(aUv+w)).xyz;
                        vec3 uv_nw = texture2D(u_image, fract(aUv+nw)).xyz;
                        vec3 uv_sw = texture2D(u_image, fract(aUv+sw)).xyz;
                        vec3 uv_ne = texture2D(u_image, fract(aUv+ne)).xyz;
                        vec3 uv_se = texture2D(u_image, fract(aUv+se)).xyz;

                        return _G0*uv + _G1*(uv_n + uv_e + uv_w + uv_s) + _G2*(uv_nw + uv_sw + uv_ne + uv_se);
                    }

                    void main( void ) {

                        const float _K0 = -20.0/6.0; // center weight
                        const float _K1 = 4.0/6.0;   // edge-neighbors
                        const float _K2 = 1.0/6.0;   // vertex-neighbors
                        const float cs = -0.6;  // curl scale
                        const float ls = 0.05;  // laplacian scale
                        const float ps = -0.8;  // laplacian of divergence scale
                        const float ds = -0.05; // divergence scale
                        const float dp = -0.04; // divergence update scale
                        const float pl = 0.3;   // divergence smoothing
                        const float ad = 6.0;   // advection distance scale
                        const float pwr = 1.0;  // power when deriving rotation angle from curl
                        const float amp = 1.0;  // self-amplification
                        const float upd = 0.8;  // update smoothing
                        const float sq2 = 0.6;  // diagonal weight

                        vec2 vUv = gl_FragCoord.xy / u_size.xy;
                        vec2 texel = 1. / u_size.xy;

                        float step_x = texel.x;
                        float step_y = texel.y;
                        vec2 n  = vec2(0.0, step_y);
                        vec2 ne = vec2(step_x, step_y);
                        vec2 e  = vec2(step_x, 0.0);
                        vec2 se = vec2(step_x, -step_y);
                        vec2 s  = vec2(0.0, -step_y);
                        vec2 sw = vec2(-step_x, -step_y);
                        vec2 w  = vec2(-step_x, 0.0);
                        vec2 nw = vec2(-step_x, step_y);

                        vec3 uv =    texture2D(u_image, fract(vUv)).xyz;
                        vec3 uv_n =  texture2D(u_image, fract(vUv+n)).xyz;
                        vec3 uv_e =  texture2D(u_image, fract(vUv+e)).xyz;
                        vec3 uv_s =  texture2D(u_image, fract(vUv+s)).xyz;
                        vec3 uv_w =  texture2D(u_image, fract(vUv+w)).xyz;
                        vec3 uv_nw = texture2D(u_image, fract(vUv+nw)).xyz;
                        vec3 uv_sw = texture2D(u_image, fract(vUv+sw)).xyz;
                        vec3 uv_ne = texture2D(u_image, fract(vUv+ne)).xyz;
                        vec3 uv_se = texture2D(u_image, fract(vUv+se)).xyz;

                        vec3 lapl  = _K0*uv + _K1*(uv_n + uv_e + uv_w + uv_s) + _K2*(uv_nw + uv_sw + uv_ne + uv_se);
                        float sp = ps * lapl.z;

                        float curl = uv_n.x - uv_s.x - uv_e.y + uv_w.y + sq2 * (uv_nw.x + uv_nw.y + uv_ne.x - uv_ne.y + uv_sw.y - uv_sw.x - uv_se.y - uv_se.x);

                        float sc = cs * sign(curl) * pow(abs(curl), pwr);

                        float div  = uv_s.y - uv_n.y - uv_e.x + uv_w.x + sq2 * (uv_nw.x - uv_nw.y - uv_ne.x - uv_ne.y + uv_sw.x + uv_sw.y + uv_se.y - uv_se.x);
                        float sd = uv.z + dp * div + pl * lapl.z;

                        vec2 norm = normz(uv.xy);

                        vec3 ab = advect(vec2(uv.x, uv.y), vUv, texel, ad);

                        float ta = amp * ab.x + ls * lapl.x + norm.x * sp + uv.x * ds * sd;
                        float tb = amp * ab.y + ls * lapl.y + norm.y * sp + uv.y * ds * sd;

                        float a = ta * cos(sc) - tb * sin(sc);
                        float b = ta * sin(sc) + tb * cos(sc);

                        vec3 abd = upd * uv + (1.0 - upd) * vec3(a,b,sd);

                        abd.z = clamp(abd.z, -1.0, 1.0);
                        abd.xy = clamp(length(abd.xy) > 1.0 ? normz(abd.xy) : abd.xy, -1.0, 1.0);
                        gl_FragColor = vec4(abd, 0.0);
                    }`,
                    program: null,
                    attributes:
                    {
                        a_position: null
                    },
                    uniforms:
                    {
                        u_size: null
                    }
                },
                colorize:
                {
                    vertex: `
                    attribute vec2 a_position;

                    void main() {
                        gl_Position = vec4(a_position, 0, 1);
                    }`,
                    fragment: `
                    #ifdef GL_ES
                    precision mediump float;
                    #endif

                    uniform vec2 u_size;
                    uniform sampler2D u_image;

                    void main( void ) {
                        vec2 texel = 1. / u_size.xy;
                        vec2 uv = gl_FragCoord.xy / u_size.xy;
                        vec3 c = texture2D(u_image, uv).xyz;
                        vec3 norm = normalize(c);

                        vec3 div = vec3(0.1) * norm.z;
                        vec3 rbcol = 0.5 + 0.6 * cross(norm.xyz, vec3(0.5, -0.4, 0.5));

                        gl_FragColor = vec4(rbcol + div, 1.0);
                    }`,
                    program: null,
                    attributes:
                    {
                        a_position: null
                    },
                    uniforms: {
                        u_size: null
                    }
                }
            },
            textures:
            {
                default: null
            }
        }
    },
    mounted ()
    {
        this.setInitWebGlContext()
        this.setInitGeometryBuffer()
        this.setInitShaderPrograms()
        this.setRenderLoop()
    },
    beforeDestroy ()
    {
        window.cancelAnimationFrame(this.static.af)
    },
    computed:
    {
        ...mapGetters([
            'getCalcs'
        ])
    },
    methods:
    {
        setInitWebGlContext ()
        {
            this.static.gl = this.$el.getContext('webgl')

            if (this.static.gl === null)
            {
                console.log('Unable to initialize WebGL. Your browser or machine may not support it.')
            }
        },
        setInitShaderPrograms ()
        {
            const gl = this.static.gl

            forEach(this.static.shaders, shader =>
            {
                shader.program = gl.createProgram()

                const vertexShader = gl.createShader(gl.VERTEX_SHADER)
                const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)

                gl.shaderSource(vertexShader, shader.vertex)
                gl.shaderSource(fragmentShader, shader.fragment)

                gl.compileShader(vertexShader)
                gl.compileShader(fragmentShader)

                gl.attachShader(shader.program, vertexShader)
                gl.attachShader(shader.program, fragmentShader)

                gl.linkProgram(shader.program)
            })
        },
        setInitGeometryBuffer ()
        {
            const gl = this.static.gl
            const buffer = gl.createBuffer()

            gl.bindBuffer(this.static.gl.ARRAY_BUFFER, buffer)
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0]), gl.STATIC_DRAW)
        },
        setDraw (width, height)
        {
            const gl = this.static.gl

            gl.clearColor(0.0, 0.0, 0.0, 0.0)
            gl.clear(gl.COLOR_BUFFER_BIT)
            gl.viewport(0, 0, width, height)
            gl.drawArrays(gl.TRIANGLES, 0, 6)
        },
        setProgram (shader)
        {
            const gl = this.static.gl
            const program = this.static.shaders[shader].program
            const attributes = this.static.shaders[shader].attributes
            const uniforms = this.static.shaders[shader].uniforms

            gl.useProgram(program)

            forEach(attributes, (attribute, key) =>
            {
                attributes[key] = gl.getAttribLocation(program, key)
            })

            forEach(uniforms, (uniform, key) =>
            {
                uniforms[key] = gl.getUniformLocation(program, key)
            })
        },
        setFrameBuffer (width, height)
        {
            const gl = this.static.gl
            const texture = gl.createTexture()

            gl.bindTexture(gl.TEXTURE_2D, texture)
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)

            const framebuffer = gl.createFramebuffer()

            gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)
            gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)

            return {
                frameBuffer: framebuffer,
                texture: texture
            }
        },
        setNoise (width, height)
        {
            const gl = this.static.gl
            const attributes = this.static.shaders.noise.attributes
            const uniforms = this.static.shaders.noise.uniforms

            gl.enableVertexAttribArray(attributes.a_position)
            gl.vertexAttribPointer(attributes.a_position, 2, gl.FLOAT, false, 0, 0)
            gl.uniform2f(uniforms.u_size, width, height)
        },
        setFluid (width, height)
        {
            const gl = this.static.gl
            const attributes = this.static.shaders.fluid.attributes
            const uniforms = this.static.shaders.fluid.uniforms

            gl.enableVertexAttribArray(attributes.a_position)
            gl.vertexAttribPointer(attributes.a_position, 2, gl.FLOAT, false, 0, 0)
            gl.uniform2f(uniforms.u_size, width, height)
        },
        setColorize (width, height)
        {
            const gl = this.static.gl
            const attributes = this.static.shaders.colorize.attributes
            const uniforms = this.static.shaders.colorize.uniforms

            gl.enableVertexAttribArray(attributes.a_position)
            gl.vertexAttribPointer(attributes.a_position, 2, gl.FLOAT, false, 0, 0)
            gl.uniform2f(uniforms.u_size, width, height)
        },
        setRenderLoop ()
        {
            this.static.af = window.requestAnimationFrame(this.setRenderLoop)

            const gl = this.static.gl
            const width = this.getCalcs.vw
            const height = this.getCalcs.vh

            this.$el.width = width
            this.$el.height = height

            if (!this.static.fr)
            {
                const noiseBuffer = this.setFrameBuffer(width, height)

                this.setProgram('noise')
                this.setNoise(width, height)
                this.setDraw(width, height)

                this.static.textures.default = noiseBuffer.texture
            }

            const fluidBuffer = this.setFrameBuffer(width, height)

            gl.bindTexture(gl.TEXTURE_2D, this.static.textures.default)

            this.setProgram('fluid')
            this.setFluid(width, height)
            this.setDraw(width, height)

            this.static.textures.default = fluidBuffer.texture

            gl.bindFramebuffer(gl.FRAMEBUFFER, null)

            this.setProgram('colorize')
            this.setColorize(width, height)
            this.setDraw(width, height)

            this.static.fr++
        }
    }
}

</script>

Однако япытаясь перенять шейдер из шадертой https://www.shadertoy.com/view/XddSRX и если я румываю свой код, он ведет себя совсем по-другому.

1 Ответ

1 голос
/ 26 октября 2019

Проблема точно такая, как указано в ошибке.

Исходная и конечная текстуры для рисования одинаковы.

При взгляде на ваш код есть один шейдер, она ссылается на текстуру, есть одна текстура, она прикреплена к кадровому буферу и привязана к единице текстуры 0 по умолчанию. Таким образом, когда вы рисуете, он используется как вход (u_texture) и как выход (текущий кадровый буфер). Это не разрешено.

Простое решение - вам нужна другая текстура. Привязывайте эту текстуру при рисовании к кадровому буферу.

Лучшее решение - вам нужны 2 разные программы шейдеров. Один для рисования в буфер кадров, который не использует текстуры в качестве входных данных, а другой для рисования на холст. Так как у вас есть один шейдер, который разветвляется на u_frame. Удалите эту ветку и разделите вещи на 2 шейдерные программы. Тот, который вычисляет цвета, затем u_frame <300, и тот, который использует текстуру. Используйте компьютерную для рисования на буфер кадров, а текстурную - для рисования текстуры кадрового холста на холсте. </p>

Несколько ссылок, которые могут или не могут быть полезны: рисование нескольких вещей , рендеринг целей , обработка изображений .

...