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() }