Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Why the example code of buffer always return error?

In the reference document(http://codea.io/reference/Shaders.html#buffer), there is a example, I want to try it, but it failed, and return error: “attempt to index a nil value( global ‘myAttribute’)"
At the same time, the uniform example code is ok. I checked it again and again,but can not find the reason.

I added 1 line to my vertex shader code:

attribute float myAttribute;

below is the example code:

-- Accessing a shader buffer
------------------------
-- Create a mesh
myMesh = mesh()

-- Assign a shader to myMesh
--  This shader has an attribute named 'myAttribute'
myMesh.shader = shader("Documents:MyShader")

-- Fetch the attribute array
myAttrBuffer = myMesh:buffer("myAttribute")

-- Resize our buffer
myAttrBuffer:resize(30)

-- Add some random numbers
for i = 1,30 do
    myAttrBuffer[i] = math.random(-50,50)
end

-- The shader will now use this data
--  when myMesh is drawn

Tagged:

Comments

  • IgnatzIgnatz Mod
    Posts: 5,396

    Can't see a problem, sorry

  • @Ignatz thanks for your response, the below is the whole code:

    -- MagicMirror
    
    -- 一个非常好的处理摄像头图像的例程
    
    -- Use this function to perform your initial setup
    function setup()
        displayMode(FULLSCREEN)
    
        -- print("Hello World!")
        cameraSource(CAMERA_FRONT)
        --cameraSource(CAMERA_BACK)
    
        spriteMode(CORNER)
    
    
        img = image(100, 100)  
    
        m = mesh()
        local w, h =WIDTH, HEIGHT
    
        -- 把整个屏幕分成两个三角形
        -- mesh 顶点坐标
        m.vertices = {
            vec2(0,0), vec2(0,h), vec2(w,h),
            vec2(0,0), vec2(w,0), vec2(w,h),
        }
        -- 纹理贴图映射坐标: 必须要与 mesh 顶点坐标一一对应起来
        m.texCoords = {
            vec2(0,0), vec2(0,1), vec2(1,1),
            vec2(0,0), vec2(1,0), vec2(1,1),
        }
    
        myColor = color(255, 255, 255, 255)
        myColorV = color(255, 0, 6, 255)
        m:setColors(myColor)
    
    
    
        m.texture = CAMERA
        m.shader = shader(mShader.vS,mShader.fS)
        --m.shader = shader("Documents:Matrix")
    
        m.shader.uniformVar = 120
    
    
    
        setContext(img)
        m:draw()
        setContext()
    
        print(m.shader.uniformVar)
    
        myAttrBuffer = m:buffer("myAttribute")
        myAttrBuffer:resize(30)
    
        for i = 1,6 do
            myAttribute[i] = math.random(-50,50)
        end
    
    
        print(m.size)
        --m:resize(10)
    
    end
    
    -- This function gets called once every frame
    function draw()
    
        -- This sets a dark background color 
        background(0, 0, 0, 255)
    
        -- This sets the line thickness
        strokeWidth(5)
    
    
    
        resetMatrix()
        translate(0,HEIGHT)
        rotate(-90)
        scale(1,1.5,1)
    
        m:draw()
    
    end
    
    
    
    mShader = { vS = [[
    //
    // A basic vertex shader
    //
    
    // 来自 Codea 的输入变量, 对应于模型视图投影矩阵
    uniform mat4 modelViewProjection;
    uniform mat4 projectionMatrix;
    uniform mat4 modelMatrix;
    uniform mat4 viewMatrix;
    
    
    // 来自 Codea 的输入: 所有的 attribute 和 uniform 类型都是只读 
    // position 对应于 mesh.vertices 表中的一个点在空间的坐标向量, 形如 [x, y, z, 1]
    // color 对应于 mesh.colors 表中的一个颜色向量, 形如 [r, g, b, a]
    // texCoord 对应于 mesh.texCoords 表中的一个点在平面的坐标向量, 形如 [x, y]
    attribute vec4 position;
    attribute vec4 color;
    attribute vec2 texCoord;
    attribute float myAttribute;
    
    
    // 发给 fragment 的输出
    varying lowp vec4 vColor;
    varying highp vec2 vTexCoord;
    
    void main()
    {
        vColor = color;
        vTexCoord = texCoord;
    
        //myAttr = myAttr+vec2(1,1);
    
        gl_Position = modelViewProjection * position;
        //gl_Position = modelMatrix*viewMatrix*projectionMatrix * position;
        //gl_Position = modelMatrix*projectionMatrix * position;
        //gl_Position = viewMatrix*projectionMatrix * position;
        //gl_Position = projectionMatrix * viewMatrix* modelMatrix* position;
    
    }
    ]],
    
    fS = [[
    //
    // A basic fragment shader
    //
    
    precision highp float;
    
    // 来自 Codea 的输入变量, 对应于 Codea 中的 mesh.texture 纹理贴图
    uniform lowp sampler2D texture;
    
    // 用于测试的变量
    uniform int uniformVar;
    
    
    // 从 vertex 发过来的输出变量
    varying lowp vec4 vColor;
    varying highp vec2 vTexCoord;
    
    void main()
    {
        lowp vec4 col = texture2D( texture, vTexCoord ) * vColor;
    
        mediump float t = col.r + col.g + col.b;
        lowp float a = t / 3.0;
        lowp float a1 = a;
    
        //myAttr = myAttr+1;
    
        // 二值化或三值化
        if(a1 < 0.33)  a = 0.0; 
        else if(a1>=0.33 && a1<0.66) a = 0.5; 
        else  a = 1.0;
    
        col.r = a;
        col.g = a;
        col.b = a;
    
        //gl_FragColor = vec4(0.15, 0.15, 0.15, a * a);
        //gl_FragColor = vec4(0.15, 0.15, 0.15, a);
        gl_FragColor = col;
    }
    ]]
    }
    
    
  • This is the error info:

    image

  • IgnatzIgnatz Mod
    edited November 2015 Posts: 5,396

    You will kick yourself #-o

       for i = 1,6 do
            --myAttribute[i] = math.random(-50,50)
            myAttrBuffer[i] = math.random(-50,50)
        end
    
  • @Ignatz sorry for this low level mistake, I copy the demo code and comment the line , but the error still there:

        -- Fetch the attribute array
        myAttrBuffer = m:buffer("myAttribute")
    
        -- Resize our buffer 
        myAttrBuffer:resize(30)
    
        -- Add some random numbers
        for i = 1,30 do
            --myAttrBuffer[i] = math.random(-50,50)
        end
    
  • IgnatzIgnatz Mod
    Posts: 5,396

    Why did you comment out the line

    myAttrBuffer[i] = math.random(-50,50)
    

    It should not be commented out

  • @Ignatz What I mean is that the result is the same--error. If I do not comment the line, the error will occur at "myAttrBuffer:resize(30)" , if I comment the line, the error will also occur at "myAttrBuffer:resize(30)".

    this is the whole code without comment:

    -- MagicMirror
    
    -- 一个非常好的处理摄像头图像的例程
    
    -- Use this function to perform your initial setup
    function setup()
        displayMode(FULLSCREEN)
    
        -- print("Hello World!")
        cameraSource(CAMERA_FRONT)
        --cameraSource(CAMERA_BACK)
    
        spriteMode(CORNER)
    
    
        img = image(100, 100)  
    
        m = mesh()
        local w, h =WIDTH, HEIGHT
    
        -- 把整个屏幕分成两个三角形
        -- mesh 顶点坐标
        m.vertices = {
            vec2(0,0), vec2(0,h), vec2(w,h),
            vec2(0,0), vec2(w,0), vec2(w,h),
        }
        -- 纹理贴图映射坐标: 必须要与 mesh 顶点坐标一一对应起来
        m.texCoords = {
            vec2(0,0), vec2(0,1), vec2(1,1),
            vec2(0,0), vec2(1,0), vec2(1,1),
        }
    
        myColor = color(255, 255, 255, 255)
        myColorV = color(255, 0, 6, 255)
        m:setColors(myColor)
    
    
    
        m.texture = CAMERA
        m.shader = shader(mShader.vS,mShader.fS)
        --m.shader = shader("Documents:Matrix")
    
        m.shader.uniformVar = 120
    
        setContext(img)
        m:draw()
        setContext()
    
        print(m.shader.uniformVar)
    
    
        -- Fetch the attribute array
        myAttrBuffer = m:buffer("myAttribute")
    
        -- Resize our buffer 
        myAttrBuffer:resize(30)
    
        -- Add some random numbers
        for i = 1,30 do
            myAttrBuffer[i] = math.random(-50,50)
        end
    
        print(m.size+100)
    
        --m:resize(10)
    
    end
    
    -- This function gets called once every frame
    function draw()
    
        -- This sets a dark background color 
        background(0, 0, 0, 255)
    
        -- This sets the line thickness
        strokeWidth(5)
    
        resetMatrix()
        translate(0,HEIGHT)
        rotate(-90)
        scale(1,1.5,1)
    
        m:draw()
    
    end
    
    
    mShader = { vS = [[
    //
    // A basic vertex shader
    //
    
    // 来自 Codea 的输入变量, 对应于模型视图投影矩阵
    uniform mat4 modelViewProjection;
    uniform mat4 projectionMatrix;
    uniform mat4 modelMatrix;
    uniform mat4 viewMatrix;
    
    
    // 来自 Codea 的输入: 所有的 attribute 和 uniform 类型都是只读 
    // position 对应于 mesh.vertices 表中的一个点在空间的坐标向量, 形如 [x, y, z, 1]
    // color 对应于 mesh.colors 表中的一个颜色向量, 形如 [r, g, b, a]
    // texCoord 对应于 mesh.texCoords 表中的一个点在平面的坐标向量, 形如 [x, y]
    attribute vec4 position;
    attribute vec4 color;
    attribute vec2 texCoord;
    attribute float myAttribute;
    
    
    // 发给 fragment 的输出
    varying lowp vec4 vColor;
    varying highp vec2 vTexCoord;
    
    void main()
    {
        vColor = color;
        vTexCoord = texCoord;
    
        //myAttr = myAttr+vec2(1,1);
    
        gl_Position = modelViewProjection * position;
        //gl_Position = modelMatrix*viewMatrix*projectionMatrix * position;
        //gl_Position = modelMatrix*projectionMatrix * position;
        //gl_Position = viewMatrix*projectionMatrix * position;
        //gl_Position = projectionMatrix * viewMatrix* modelMatrix* position;
    
    }
    ]],
    
    fS = [[
    //
    // A basic fragment shader
    //
    
    precision highp float;
    
    // 来自 Codea 的输入变量, 对应于 Codea 中的 mesh.texture 纹理贴图
    uniform lowp sampler2D texture;
    
    // 用于测试的变量
    uniform int uniformVar;
    
    
    // 从 vertex 发过来的输出变量
    varying lowp vec4 vColor;
    varying highp vec2 vTexCoord;
    
    void main()
    {
        lowp vec4 col = texture2D( texture, vTexCoord ) * vColor;
    
        mediump float t = col.r + col.g + col.b;
        lowp float a = t / 3.0;
        lowp float a1 = a;
    
        //myAttr = myAttr+1;
    
        // 二值化或三值化
        if(a1 < 0.33)  a = 0.0; 
        else if(a1>=0.33 && a1<0.66) a = 0.5; 
        else  a = 1.0;
    
        col.r = a;
        col.g = a;
        col.b = a;
    
        //gl_FragColor = vec4(0.15, 0.15, 0.15, a * a);
        //gl_FragColor = vec4(0.15, 0.15, 0.15, a);
        gl_FragColor = col;
    }
    ]]
    }
    
    
  • dave1707dave1707 Mod
    Posts: 8,808

    @binaryblues I'm not sure what you're doing with myAttrBuffer, but if I comment out its 3 uses, the code runs without problems. It show a black/grey image of me from the camera.

  • Posts: 2,020

    @binaryblues

    The problem is this. I've run into this issue many times with shaders. An interesting thing about custom attribute buffers and uniform arrays in shaders is, you have to actually use them in the shader for them to exist. Just declaring them in the shader preamble is not enough. So, for instance, if in the vertex shader you change vColor = color; to vColor = color * myAttribute; the error disappears.

    I ran into the exact same thing. I was thinking "always code iteratively" so you gradually add an attribute buffer one piece at a time. But until the attribute is being used for something in the main void loop, it's as if it doesn't exist, and you'll get errors like this.

    This also applies to uniform arrays, but not to any other kind of variable.

    If only Codea Talk had an "upvote this answer" button.... B-) ~O)

  • @dave1707 @yojimbo2000 thanks!
    I understand it! We must use a var in the function, otherwise it will set nil.

    Add "vColor* myAttribute;" into the main of vertex shader, then it will get the value! I will write it in my Codea FAQ :)

    Thanks guys! It took me two days, yesterday, in my dream, I am thinking about it....

Sign In or Register to comment.