go-gl第一个三角形(三)

1. 简述


根据OpenGL版本的不同,在场景中绘制几何体的方式和使用的OpenGL函数有很大的差别,概括起来包括:

OpenGL模式方式备注
LegecyOpenGL立即模式
LegecyOpenGLDispalyList(显示列表)
LegecyOpenGLVertexArray的方式
LegecyOpenGLVBO方式可以忽略VAO
CoreProfileVBO方式必须使用VAO
CoreProfileVBO方式-DSA(>=4.5)使用DSA(Direct State Access)扩展的接口

针对表中Legecy OpenGL的几种方式,可以参考:《VA、VAO和VBO API备忘》

2. 基本绘制


三角形的顶点可以使用golang中的切片来定义:


var vertices = []float32{
    -0.5, -0.5, 0.0,
    0.5, -0.5, 0.0,
    0.0, 0.5, 0.0,
}

如果使用OpenGL 2.1版本,可以使用立即模式来快速绘制三角形(调用glVertex*这样的函数)


func draw() {
    gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

    gl.Color3f(1.0, 0.5, 0.2)

    gl.Begin(gl.TRIANGLES)
    gl.Vertex3f(vertices[0], vertices[1], vertices[2])
    gl.Vertex3f(vertices[3], vertices[4], vertices[5])
    gl.Vertex3f(vertices[6], vertices[7], vertices[8])
    gl.End()
}

3. VBO方式绘制(3.3)

在OpenGL 3.3以后的版本,绘制几何体需要使用VBO的方式。由于在3.3以后的版本OpenGL必须使用Shader来绘制,代码中会存在很多shader处理相关的代码,主要包括:
1. shader文件读取
2. shader的源码编译
3. program链接shader和使用program


func compileShader(source string, shaderType uint32) (uint32, error) {
    shader := gl.CreateShader(shaderType)

    csources, free := gl.Strs(source)
    gl.ShaderSource(shader, 1, csources, nil)
    free()

    gl.CompileShader(shader)

    var status int32

    gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status)
    if status == gl.FALSE {
        var logLength int32
        gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &logLength)

        log := strings.Repeat("\x00", int(logLength+1))
        gl.GetShaderInfoLog(shader, logLength, nil, gl.Str(log))

        return 0, fmt.Errorf("failed to compile %v: %v", source, log)
    }

    return shader, nil
}

绘制的代码需要创建VBO和VAO,同时使用接口将数据传输到VBO中,代码如下

    var vbo uint32
    gl.GenBuffers(1, &vbo)
    gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
    gl.BufferData(gl.ARRAY_BUFFER, 4*len(vertices), gl.Ptr(vertices), gl.STATIC_DRAW)

    gl.GenVertexArrays(1, &vao)
    gl.BindVertexArray(vao)
    gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, gl.PtrOffset(0))
    gl.EnableVertexAttribArray(0)

    gl.BindVertexArray(0)
    gl.BindBuffer(gl.ARRAY_BUFFER, 0)

    vertexShader, err := compileShader(vertexShaderSourceCode, gl.VERTEX_SHADER)
    if err != nil {
        panic(err)
    }

    fragmentShader, err := compileShader(fragmentShaderSourceCode, gl.FRAGMENT_SHADER)
    if err != nil {
        panic(err)
    }

    program = gl.CreateProgram()
    gl.AttachShader(program, vertexShader)
    gl.AttachShader(program, fragmentShader)
    gl.LinkProgram(program)


完成设置之后,绘制三角形


func draw() {
    gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

    gl.UseProgram(program)

    gl.BindVertexArray(vao)
    gl.DrawArrays(gl.TRIANGLES, 0, int32(len(vertices)/3))
}

Shader部分非常简单,顶点shader直接读入数据并赋值给gl_Position,片元Shader直接设置颜色(需要注意golang中的跨行字符串格式)


var vertexShaderSourceCode = `
    #version 330 core
    layout (location=0) in vec3 pos;

    void main() {
        gl_Position = vec4(pos.x, pos.y, pos.z ,1.0);
    }
` + "\x00"

var fragmentShaderSourceCode = `
    #version 330 core
    out vec4 color;
    void main() {
        color = vec4(1.0, 0.5, 0.2, 1.0);
    }
` + "\x00"

3. VBO方式绘制(4.5 DSA)

OpenGL 4.5中的代码和3.3大体相同,不过由于DSA引入有部分接口略有差别,一个主要的区别是不需要在写很多gl.Bind函数了,主要的修改如下:

    var vbo uint32

    // 3.3
    //gl.GenBuffers(1, &vbo)
    //gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
    //gl.BufferData(gl.ARRAY_BUFFER, 
    //4*len(vertices), gl.Ptr(vertices), gl.STATIC_DRAW)

    // 4.5 DSA
    gl.CreateBuffers(1, &vbo)
    gl.Ptr(vertices), 0)

    //gl.GenVertexArrays(1, &vao)
    //gl.BindVertexArray(vao)

    //4.5 DSA
    gl.CreateVertexArrays(1, &vao)

    gl.BindVertexArray(vao)
    gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
    gl.VertexAttribPointer(0, 3, gl.FLOAT, 
    false, 0, gl.PtrOffset(0))
    gl.EnableVertexAttribArray(0)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值