golang game development study notes - golang draw a square with a time-varying colors

Although the work uses only the basic javaand javascriptbut has been more interested in golang, recently nothing else, wanted to write a game (also a blogger dream has always been) but if the direct effect on the game engine would not achieve the learning, so learn from scratch opengl, golangunder the opengldocument is relatively small, the application does not seem wide, shining only C++document Zhaomaohuahu the
main reference tutorial these two sites
learnOpenGl Chinese translation, use C++implementation.
Go with OpenGL Tutorial unique in golang use opengl tutorials can be found, very early.

1. Related concepts

  1. opengl

Developed by the Khronos Group and a maintenance specification (Specification). The specification defines how strictly the implementation of each function, and their output value. As for the interior of each specific function is how to achieve (Implement), will be the developer of OpenGL library discretion (translation: here the developer is the person to write OpenGL library). Because the details of OpenGL specification does not achieve a predetermined specific OpenGL library allows for different implementations, and as long as its function results matching the specification (i.e., as the user does not feel the difference in the function).

  1. glfw

Used to create the window, context, and interfaces to receive input api and events.

  1. shader(着色器)

Running applets on the GPU. These small programs to a specific part of the graphics rendering pipeline and run, the use of a C-like language called GLSL written, there is a vertex shaders and fragment shaders are two kinds of concrete doing is not very thorough I understand now only the door as he rendered image of a different phase of the tool?

  1. program

After the merge multiple shader and final link to complete version.

  1. Vertex Buffer Object (顶点缓冲区对象,简称vbo)

A plurality of objects stored vertices, a large number of one-time data transmission to the graphics card, it is easily understood that, if no buffer, make a vertex of each image are sent to the GPU, and the buffer is the same as the programming language thought.

  1. Vertex Array Object(顶点数组对象,简称vao)

Vbo and save one or more corresponding vertex attributes, not only is there vbo rendered image directly, but also need to bind a variety of attributes, such as normals, color information, indexes, etc., after drawing each have the same configuration vao do not re-bind when vbo

  1. Element Buffer Object(索引缓冲对象,简称ebo)

The concept here on the very clear, and not elaborated here

2. dependence

golangIn the country seems to be qiang, the good news opengland glfwdependencies are posted githubon the configured gopathdirectly using the system variable go getcommand to download the dependencies. It is noted that the installation opengldependencies needed gcc, if not, need to be installed mingwor TDM-GCC, as dependent on the installation command

go get -u github.com/go-gl/gl/v4.6-core/gl
go get github.com/go-gl/glfw/v3.2/glfw

3. Initialize window

import(
    "github.com/go-gl/glfw/v3.2/glfw"
)

The introduction of dependence

 if err := glfw.Init(); err != nil {
            panic(err)
    }
    glfw.WindowHint(glfw.Resizable, glfw.False)
    window, err := glfw.CreateWindow(width, height, "Conway's Game of Life", nil, nil)
    if err != nil {
            panic(err)
    }

    window.MakeContextCurrent()

Initialization and set the properties window, set the window size can not be changed here, to note is that GLFWneeds to be called in its thread after being initialized in

4. Preparation of shader programs and shader

The aforementioned use shader GLSLlanguage, studied the chain of responsibility pattern design students can shader understood as different parts of the chain of responsibility, and the output of the previous program is entering a program, we were to write a vertex shader and fragment shaders and write using a openglcompiled function

import(
	"github.com/go-gl/gl/v4.1-core/gl"
	"strings"
	"fmt"
)
const(
	VertexShaderSource = `
		#version 410
		in vec3 vp;
		void main(){
			gl_Position = vec4(vp,1.0);
		}
	` + "\x00"
	FragmentShaderSource = `
		#version 410
		out vec4 frag_colour;
		uniform vec4 FragColor;
		void main() {
			frag_colour = FragColor;
		}
	` + "\x00"
)
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
}

Then we initialize shaders and shader added

if err := gl.Init(); err != nil {
            panic(err)
    }
    version := gl.GoStr(gl.GetString(gl.VERSION))
    log.Println("OpenGL version", version)
    vertexShader, err := shader.CompileShader(shader.VertexShaderSource, gl.VERTEX_SHADER)
    if err != nil {
        panic(err)
    }
    fragmentShader, err := shader.CompileShader(shader.FragmentShaderSource, gl.FRAGMENT_SHADER)
    if err != nil {
        panic(err)
    }
    prog := gl.CreateProgram()
    gl.AttachShader(prog, vertexShader)
    gl.AttachShader(prog, fragmentShader)    
    gl.Viewport(0,0,width,height)
    gl.LinkProgram(prog)

The construct an image, and a buffer

Define two slices

var (
    vertices = []float32{
        -0.5, -0.5, 0.0,
        -0.5, 0.5, 0.0,
        0.5, 0.5, 0.0,
        0.5, -0.5, 0.0,
    }
    indices = []uint32{
        0, 1, 2,
        2, 3, 0,
    }
)

Stored within the first slice of all the vertices constituting the two triangles are needed, since we will use ebo, the two directly repeated vertices omitted, and each row of the second slice index of the previous section representing vertices, respectively corresponding triangular configuration.
Generate and bindvao

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

var vao uint32
gl.GenVertexArrays(1, &vao)
gl.BindVertexArray(vao)
gl.EnableVertexAttribArray(0)
gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, gl.Ptr(nil))

var ebo uint32
gl.GenBuffers(2,&ebo)
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER,ebo)
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER,4*len(indices),gl.Ptr(indices),gl.STATIC_DRAW)

Finally maindraw function

for !window.ShouldClose() {
    gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
    timeValue := glfw.GetTime()
    greenValue := float32(math.Sin(timeValue) / 2.0 + 0.5)
    vertexColorLocation := gl.GetUniformLocation(prog,gl.Str("FragColor\x00"))
    gl.UseProgram(prog)
    glBindVertexArray(vao);
    gl.Uniform4f(vertexColorLocation,0,greenValue,0,1)
    gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, gl.PtrOffset(0))
    glfw.PollEvents()
    window.SwapBuffers()
}

The final operating results
Here Insert Picture Description
complete code is as follows

package main

import(
    "github.com/go-gl/glfw/v3.2/glfw"
    "github.com/go-gl/gl/v4.1-core/gl"
    "log"
    "legend/shader"
    "runtime"
    "math"
    "strings"
	"fmt"
)
const (
    width  = 500
    height = 500
    VertexShaderSource = `
		#version 410
		in vec3 vp;
		void main(){
			gl_Position = vec4(vp,1.0);
		}
	` + "\x00"
	FragmentShaderSource = `
		#version 410
		out vec4 frag_colour;
		uniform vec4 FragColor;
		void main() {
			frag_colour = FragColor;
		}
	` + "\x00"
)

var (
    vertices = []float32{
        -0.5, -0.5, 0.0,
        -0.5, 0.5, 0.0,
        0.5, 0.5, 0.0,
        0.5, -0.5, 0.0,
    }
    indices = []uint32{
        0, 1, 2,
        2, 3, 0,
    }
)
func main() {
    runtime.LockOSThread()
    window := initGlfw()
    defer glfw.Terminate()
    program := initOpenGL()
    vao := makeVao(vertices,indices)
    for !window.ShouldClose() {
        draw(vao, window, program)
    }
    glfw.Terminate()
}
func initGlfw() *glfw.Window {
    if err := glfw.Init(); err != nil {
            panic(err)
    }
    glfw.WindowHint(glfw.Resizable, glfw.False)
    window, err := glfw.CreateWindow(width, height, "Conway's Game of Life", nil, nil)
    if err != nil {
            panic(err)
    }

    window.MakeContextCurrent()
    return window
}

func initOpenGL() uint32 {
    if err := gl.Init(); err != nil {
            panic(err)
    }
    version := gl.GoStr(gl.GetString(gl.VERSION))
    log.Println("OpenGL version", version)
    vertexShader, err := shader.CompileShader(shader.VertexShaderSource, gl.VERTEX_SHADER)
    if err != nil {
        panic(err)
    }
    fragmentShader, err := shader.CompileShader(shader.FragmentShaderSource, gl.FRAGMENT_SHADER)
    if err != nil {
        panic(err)
    }
    prog := gl.CreateProgram()
    gl.AttachShader(prog, vertexShader)
    gl.AttachShader(prog, fragmentShader)    
    gl.Viewport(0,0,width,height)
    gl.LinkProgram(prog)
    return prog
}


func makeVao(points []float32,indices []uint32) uint32 {
    var vbo uint32
    gl.GenBuffers(1, &vbo)
    gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
    gl.BufferData(gl.ARRAY_BUFFER, 4*len(points), gl.Ptr(points), gl.STATIC_DRAW)

    var vao uint32
    gl.GenVertexArrays(1, &vao)
    gl.BindVertexArray(vao)
    gl.EnableVertexAttribArray(0)
    gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, gl.Ptr(nil))

    if(indices != nil){
        var ebo uint32
        gl.GenBuffers(2,&ebo)
        gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER,ebo)
        gl.BufferData(gl.ELEMENT_ARRAY_BUFFER,4*len(indices),gl.Ptr(indices),gl.STATIC_DRAW)

    }
    return vao
}

func draw(vao uint32, window *glfw.Window, program uint32) {
    gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
    timeValue := glfw.GetTime()
    greenValue := float32(math.Sin(timeValue) / 2.0 + 0.5)
    vertexColorLocation := gl.GetUniformLocation(program,gl.Str("FragColor\x00"))
    gl.UseProgram(program)
    gl.BindVertexArray(vao)
    gl.Uniform4f(vertexColorLocation,0,greenValue,0,1)

    //gl.DrawArrays(gl.TRIANGLES, 0, 4)
    gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, gl.PtrOffset(0))
    glfw.PollEvents()
    window.SwapBuffers()
}
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
}

Guess you like

Origin blog.csdn.net/qq_35488769/article/details/94209069