试图从帧缓冲区传递纹理会导致L_INVALID_OPERATION:glDrawArrays:绘制的源纹理和目标纹理相同

问题描述 投票:0回答:1

我是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>
javascript webgl framebuffer
1个回答
0
投票

问题与错误中所述的完全一样。

绘制的源纹理和目标纹理相同。

[查看您的代码,有一个着色器,它引用了一个纹理,有一个纹理,它附加到帧缓冲区,并且绑定到默认的纹理单元0。因此,在绘制时,它既用作输入(u_texture),又用作输出(当前帧缓冲区)。不允许的。

简单的解决方案是您需要另一个纹理。绘制到帧缓冲区时绑定该纹理。

更好的解决方案是您需要2个不同的着色器程序。一种用于绘制到不使用纹理作为输入的帧缓冲区,另一种用于绘制到画布。因为它是一个在u_frame上分支的着色器。删除该分支,并将其分成2个着色器程序。然后计算颜色的u_frame <300,然后使用纹理的颜色。使用计算之一绘制到帧缓冲区,使用纹理之一绘制帧缓冲区的纹理到画布。

一些可能有用或无效的链接:drawing multiple thingsrender targetsimage processing

© www.soinside.com 2019 - 2024. All rights reserved.