120 lines
3.6 KiB
Go
Executable File
120 lines
3.6 KiB
Go
Executable File
package render
|
|
|
|
import (
|
|
"time"
|
|
"unsafe"
|
|
|
|
"github.com/Edgaru089/gl01/internal/asset"
|
|
"github.com/Edgaru089/gl01/internal/util/itype"
|
|
"github.com/Edgaru089/gl01/internal/world"
|
|
"github.com/go-gl/gl/all-core/gl"
|
|
"github.com/go-gl/mathgl/mgl32"
|
|
)
|
|
|
|
// WorldRenderer holds texture/shader resource and viewport
|
|
// information for world rendering.
|
|
type WorldRenderer struct {
|
|
shader *Shader
|
|
texture *Texture
|
|
|
|
vao, vbo uint32
|
|
vbolen int
|
|
vertex []world.Vertex
|
|
|
|
// for testing!
|
|
initTime time.Time
|
|
}
|
|
|
|
// The default WorldRenderer.
|
|
var DefaultWorldRenderer WorldRenderer
|
|
|
|
// Init initializes the WorldRenderer.
|
|
func (r *WorldRenderer) Init(w *world.World) (err error) {
|
|
|
|
r.shader, err = NewShader(asset.WorldShaderVert, asset.WorldShaderFrag)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
asset.InitWorldTextureAtlas()
|
|
r.texture = NewTextureRGBA(asset.WorldTextureAtlas.Image)
|
|
r.shader.SetUniformTexture("tex", r.texture)
|
|
|
|
r.shader.SetUniformMat4("model", mgl32.Ident4())
|
|
// and view and projection uniforms not yet set
|
|
gl.BindFragDataLocation(r.shader.Handle(), 0, gl.Str("outputColor\x00"))
|
|
|
|
gl.GenVertexArrays(1, &r.vao)
|
|
gl.BindVertexArray(r.vao)
|
|
gl.GenBuffers(1, &r.vbo)
|
|
gl.BindBuffer(gl.ARRAY_BUFFER, r.vbo)
|
|
|
|
gensync := make(chan []world.Vertex, len(w.Chunks))
|
|
for _, c := range w.Chunks {
|
|
chunk := c
|
|
go func() {
|
|
arr := chunk.AppendVertex([]world.Vertex{})
|
|
gensync <- arr
|
|
}()
|
|
}
|
|
for range w.Chunks {
|
|
r.vertex = append(r.vertex, (<-gensync)...)
|
|
}
|
|
close(gensync)
|
|
|
|
gl.BufferData(gl.ARRAY_BUFFER, int(unsafe.Sizeof(world.Vertex{}))*len(r.vertex), gl.Ptr(r.vertex), gl.DYNAMIC_DRAW)
|
|
|
|
vertAttrib := uint32(gl.GetAttribLocation(r.shader.Handle(), gl.Str("vert\x00")))
|
|
gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, int32(unsafe.Sizeof(world.Vertex{})), gl.PtrOffset(int(unsafe.Offsetof(world.Vertex{}.World))))
|
|
|
|
normalAttrib := uint32(gl.GetAttribLocation(r.shader.Handle(), gl.Str("normal\x00")))
|
|
gl.VertexAttribPointer(normalAttrib, 3, gl.FLOAT, false, int32(unsafe.Sizeof(world.Vertex{})), gl.PtrOffset(int(unsafe.Offsetof(world.Vertex{}.Normal))))
|
|
|
|
texCoordAttrib := uint32(gl.GetAttribLocation(r.shader.Handle(), gl.Str("vertTexCoord\x00")))
|
|
gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, false, int32(unsafe.Sizeof(world.Vertex{})), gl.PtrOffset(int(unsafe.Offsetof(world.Vertex{}.Texture))))
|
|
|
|
lightAttrib := uint32(gl.GetAttribLocation(r.shader.Handle(), gl.Str("light\x00")))
|
|
gl.VertexAttribPointer(lightAttrib, 1, gl.FLOAT, false, int32(unsafe.Sizeof(world.Vertex{})), gl.PtrOffset(int(unsafe.Offsetof(world.Vertex{}.Light))))
|
|
|
|
gl.EnableVertexAttribArray(vertAttrib)
|
|
gl.EnableVertexAttribArray(normalAttrib)
|
|
gl.EnableVertexAttribArray(texCoordAttrib)
|
|
gl.EnableVertexAttribArray(lightAttrib)
|
|
|
|
w.EnableVertexArrayAttrib(vertAttrib)
|
|
w.EnableVertexArrayAttrib(normalAttrib)
|
|
w.EnableVertexArrayAttrib(texCoordAttrib)
|
|
w.EnableVertexArrayAttrib(lightAttrib)
|
|
|
|
gl.Enable(gl.CULL_FACE)
|
|
gl.Enable(gl.DEPTH_TEST)
|
|
gl.DepthFunc(gl.LESS)
|
|
|
|
r.initTime = time.Now()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *WorldRenderer) Render(world *world.World, view *View) {
|
|
|
|
r.shader.UseProgram()
|
|
r.shader.BindTextures()
|
|
|
|
r.shader.SetUniformMat4("view", view.view)
|
|
r.shader.SetUniformMat4("projection", mgl32.Perspective(view.fovy, view.aspect, 0.1, 200))
|
|
r.shader.SetUniformVec3f("sun", itype.Vec3f{-0.2, 1, 0.8}.Normalize())
|
|
|
|
// for testing!
|
|
//model := mgl32.HomogRotate3D(float32(time.Since(r.initTime).Seconds()), mgl32.Vec3{0, 1, 0})
|
|
//r.shader.SetUniformMat4("model", model)
|
|
|
|
//r.shader.SetUniformMat4("view", r.view)
|
|
|
|
gl.BindVertexArray(r.vao)
|
|
gl.BindBuffer(gl.ARRAY_BUFFER, r.vbo)
|
|
gl.DrawArrays(gl.TRIANGLES, 0, int32(len(r.vertex)))
|
|
|
|
world.Render()
|
|
//world.Chunk(0, 0).Render()
|
|
}
|