golang游戏开发学习笔记-创建一个能自由探索的3D世界

localCamera := &LocalCamera{position:position,

front:front,

wordUp:wordUp,

yaw:yaw,

pitch:pitch,

movementSpeed:movementSpeed,

mouseSensitivity:mouseSensitivity,

zoom:zoom,

constrainPitch:constrainPitch}

localCamera.updateCameraVectors()

return localCamera

}

//获取当前透视矩阵

func (localCamera *LocalCamera) GetProjection(width float32, height float32) *float32{

projection := mgl32.Perspective(mgl32.DegToRad(localCamera.zoom), float32(width)/height, 0.1, 100.0)

return &projection[0]

}

//鼠标移动回调

func (localCamera *LocalCamera) ProcessMouseMovement(xoffset float32, yoffset float32){

xoffset *= localCamera.mouseSensitivity

yoffset *= localCamera.mouseSensitivity

localCamera.yaw += float64(xoffset)

localCamera.pitch += float64(yoffset)

// Make sure that when pitch is out of bounds, screen doesn’t get flipped

if (localCamera.constrainPitch){

if (localCamera.pitch > 89.0){

localCamera.pitch = 89.0

}

if (localCamera.pitch < -89.0){

localCamera.pitch = -89.0

}

}

localCamera.updateCameraVectors();

}

//鼠标滑动回调

func (localCamera *LocalCamera) ProcessMouseScroll(yoffset float32){

if (localCamera.zoom >= 1.0 && localCamera.zoom <= 45.0){

localCamera.zoom -= yoffset;

}

if (localCamera.zoom <= 1.0){

localCamera.zoom = 1.0;

}

if (localCamera.zoom >= 45.0){

localCamera.zoom = 45.0;

}

}

//键盘回调

func (localCamera *LocalCamera) ProcessKeyboard(direction Direction, deltaTime float32){

velocity := localCamera.movementSpeed * deltaTime;

if (direction == FORWARD){

localCamera.position = localCamera.position.Add(localCamera.front.Mul(velocity))

}

if (direction == BACKWARD){

localCamera.position = localCamera.position.Sub(localCamera.front.Mul(velocity))

}

if (direction == LEFT){

localCamera.position = localCamera.position.Sub(localCamera.right.Mul(velocity))

}

if (direction == RIGHT){

localCamera.position = localCamera.position.Add(localCamera.right.Mul(velocity))

}

}

//获取view

func (localCamera *LocalCamera) GetViewMatrix() *float32{

target := localCamera.position.Add(localCamera.front)

view := mgl32.LookAtV(localCamera.position,target, localCamera.up)

return &view[0]

}

//更新view

func (localCamera *LocalCamera) updateCameraVectors(){

x := math.Cos(mgl64.DegToRad(localCamera.yaw)) * math.Cos(mgl64.DegToRad(localCamera.pitch))

y := math.Sin(mgl64.DegToRad(localCamera.pitch))

z := math.Sin(mgl64.DegToRad(localCamera.yaw)) * math.Cos(mgl64.DegToRad(localCamera.pitch));

localCamera.front = mgl32.Vec3{float32(x),float32(y),float32(z)}

localCamera.right = localCamera.front.Cross(localCamera.wordUp).Normalize()

localCamera.up = localCamera.right.Cross(localCamera.front).Normalize()

}

3.创建着色器

上一篇文章中我写过创建一个着色器的全部流程,这里我们将其封装为一个着色器类,可以直接从文件中构造并编译出着色器

package shader

import (

“io/ioutil”

“fmt”

“github.com/go-gl/gl/v4.1-core/gl”

“strings”

)

type LocalShader struct{

ID uint32

}

func (shader *LocalShader) Use(){

gl.UseProgram(shader.ID)

}

func (shader *LocalShader) SetBool(name string, value bool){

var a int32 = 0;

if(value){

a = 1

}

gl.Uniform1i(gl.GetUniformLocation(shader.ID, gl.Str(name + “\x00”)), a)

}

func (shader *LocalShader) SetInt(name string, value int32){

gl.Uniform1i(gl.GetUniformLocation(shader.ID, gl.Str(name + “\x00”)), value)

}

func (shader *LocalShader) SetFloat(name string, value float32){

gl.Uniform1f(gl.GetUniformLocation(shader.ID, gl.Str(name + “\x00”)), value)

}

func (shader *LocalShader) SetMatrix4fv(name string, value *float32){

gl.UniformMatrix4fv(gl.GetUniformLocation(shader.ID, gl.Str(name + “\x00”)), 1,false,value)

}

func NewLocalShader(vertexPath string, fragmentPath string) *LocalShader{

vertexString, err := ioutil.ReadFile(vertexPath)

if err != nil{

panic(err)

}

fragmentString, err := ioutil.ReadFile(fragmentPath)

if err != nil{

panic(err)

}

return NewStringShader(string(vertexString),string(fragmentString))

}

func NewStringShader(vertexString string, fragmentString string) *LocalShader{

vertexShader,err := compileShader(vertexString+“\x00”, gl.VERTEX_SHADER)

if err != nil{

panic(err)

}

fragmentShader,err := compileShader(fragmentString+“\x00”, gl.FRAGMENT_SHADER)

if err != nil{

panic(err)

}

progID := gl.CreateProgram()

gl.AttachShader(progID, vertexShader)

gl.AttachShader(progID, fragmentShader)

gl.LinkProgram(progID)

gl.DeleteShader(vertexShader)

gl.DeleteShader(fragmentShader)

return &LocalShader{ ID: progID}

}

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

}

两个着色器代码如下

#version 410 core

layout (location = 0) in vec3 aPos;

layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

uniform mat4 model;

uniform mat4 view;

uniform mat4 projection;

void main(){

gl_Position = projection * view * model * vec4(aPos,1.0);

TexCoord = aTexCoord;

}

#version 410 core

out vec4 FragColor;

in vec2 TexCoord;

uniform sampler2D texture1;

uniform sampler2D texture2;

void main()

{

FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.5);

}

4.整合

我们在main方法中对以上内容进行整合,包括按键输入处理,鼠标移动处理等

package main

import(

“github.com/go-gl/glfw/v3.2/glfw”

“github.com/go-gl/gl/v4.1-core/gl”

“log”

“legend/shader”

“runtime”

“legend/texture”

“legend/camera”

“github.com/go-gl/mathgl/mgl32”

)

const (

width = 800

height = 600

)

var (

vertices = []float32 {

-0.5, -0.5, -0.5, 0.0, 0.0,

0.5, -0.5, -0.5, 1.0, 0.0,

0.5, 0.5, -0.5, 1.0, 1.0,

0.5, 0.5, -0.5, 1.0, 1.0,

-0.5, 0.5, -0.5, 0.0, 1.0,

-0.5, -0.5, -0.5, 0.0, 0.0,

-0.5, -0.5, 0.5, 0.0, 0.0,

0.5, -0.5, 0.5, 1.0, 0.0,

0.5, 0.5, 0.5, 1.0, 1.0,

0.5, 0.5, 0.5, 1.0, 1.0,

-0.5, 0.5, 0.5, 0.0, 1.0,

-0.5, -0.5, 0.5, 0.0, 0.0,

-0.5, 0.5, 0.5, 1.0, 0.0,

-0.5, 0.5, -0.5, 1.0, 1.0,

-0.5, -0.5, -0.5, 0.0, 1.0,

-0.5, -0.5, -0.5, 0.0, 1.0,

-0.5, -0.5, 0.5, 0.0, 0.0,

-0.5, 0.5, 0.5, 1.0, 0.0,

0.5, 0.5, 0.5, 1.0, 0.0,

0.5, 0.5, -0.5, 1.0, 1.0,

0.5, -0.5, -0.5, 0.0, 1.0,

0.5, -0.5, -0.5, 0.0, 1.0,

0.5, -0.5, 0.5, 0.0, 0.0,

0.5, 0.5, 0.5, 1.0, 0.0,

-0.5, -0.5, -0.5, 0.0, 1.0,

0.5, -0.5, -0.5, 1.0, 1.0,

0.5, -0.5, 0.5, 1.0, 0.0,

0.5, -0.5, 0.5, 1.0, 0.0,

-0.5, -0.5, 0.5, 0.0, 0.0,

-0.5, -0.5, -0.5, 0.0, 1.0,

-0.5, 0.5, -0.5, 0.0, 1.0,

0.5, 0.5, -0.5, 1.0, 1.0,

0.5, 0.5, 0.5, 1.0, 0.0,

0.5, 0.5, 0.5, 1.0, 0.0,

-0.5, 0.5, 0.5, 0.0, 0.0,

-0.5, 0.5, -0.5, 0.0, 1.0,

};

position = []mgl32.Mat3{

mgl32.Mat3{0,0,0},

mgl32.Mat3{2,5,-15},

mgl32.Mat3{-1.5,-2.2,-2.5},

}

deltaTime = float32(0.0); // time between current frame and last frame

lastFrame = float32(0.0);

acamera = camera.NewDefaultCamera()

firstMouse = true

lastX = width / 2.0

lastY = height / 2.0

)

func main() {

runtime.LockOSThread()

window := initGlfw()

defer glfw.Terminate()

initOpenGL()

vao,vbo := makeVao(vertices,nil)

shader := shader.NewLocalShader(“./shader/shader-file/shader.vs”,“./shader/shader-file/shader.fs”)

shader.Use()

shader.SetInt(“texture1”, 0)

shader.SetInt(“texture2”, 1)

texture1 := texture.NewLocalTexture(“./texture/texture-file/face.jpg”,gl.TEXTURE0)

texture2 := texture.NewLocalTexture(“./texture/texture-file/wood.jpg”,gl.TEXTURE1)

texture1.Use()

texture2.Use()

projection := acamera.GetProjection(width,height)

shader.SetMatrix4fv(“projection”, projection)

for !window.ShouldClose() {

currentFrame := float32(glfw.GetTime());

deltaTime = currentFrame - lastFrame;

lastFrame = currentFrame;

clear()

texture1.Use()

texture2.Use()

view := acamera.GetViewMatrix()

shader.SetMatrix4fv(“view”,view)

for _, v := range position {

model := mgl32.HomogRotate3DX(float32(glfw.GetTime())).Mul4(mgl32.HomogRotate3DY(float32(glfw.GetTime())))

model = mgl32.Translate3D(v[0],v[1],v[2]).Mul4(model)

shader.SetMatrix4fv(“model”,&model[0])

draw(vao)

}

processInput(window)

glfw.PollEvents()

window.SwapBuffers()

}

gl.DeleteVertexArrays(1, &vao);

gl.DeleteBuffers(1, &vbo);

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, “test”, nil, nil)

window.SetCursorPosCallback(mouse_callback)

if err != nil {

panic(err)

}

window.MakeContextCurrent()

window.SetInputMode(glfw.CursorMode,glfw.CursorDisabled)

return window

}

func initOpenGL(){

if err := gl.Init(); err != nil {

panic(err)

}

version := gl.GoStr(gl.GetString(gl.VERSION))

log.Println(“OpenGL version”, version)

gl.Enable(gl.DEPTH_TEST)

}

func makeVao(points []float32,indices []uint32) (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.VertexAttribPointer(0, 3, gl.FLOAT, false, 5 * 4, gl.PtrOffset(0))

gl.EnableVertexAttribArray(0)

gl.VertexAttribPointer(1, 2, gl.FLOAT, false, 5 * 4, gl.PtrOffset(3 * 4))

gl.EnableVertexAttribArray(1)

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,vbo

}

func processInput(window *glfw.Window){

if(window.GetKey(glfw.KeyW) == glfw.Press){

acamera.ProcessKeyboard(camera.FORWARD,deltaTime)

}

if(window.GetKey(glfw.KeyS) == glfw.Press){

acamera.ProcessKeyboard(camera.BACKWARD,deltaTime)

}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-FkKE2z60-1712871063146)]

[外链图片转存中…(img-Q8j9Ix4g-1712871063147)]

[外链图片转存中…(img-0kLhBkoe-1712871063147)]

[外链图片转存中…(img-XoiKNuL7-1712871063147)]

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

img
  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值