semi-transparent water rendering (TODO)

This commit is contained in:
2022-01-29 00:43:11 +08:00
parent 904221ac14
commit fea09c5012
18 changed files with 250 additions and 68 deletions

View File

@ -36,7 +36,8 @@ type BlockAppearance struct {
data itype.Dataset,
world *World,
vertexArray []Vertex,
) []Vertex
vertexArrayWater []Vertex,
) (verts []Vertex, waters []Vertex)
}
// BlockBehaviour describes a kind of block of the same Major ID.

View File

@ -10,7 +10,7 @@ type WaterBehaviour struct{}
func (WaterBehaviour) Static() bool { return false }
func (WaterBehaviour) RequireDataset() bool { return false }
func (WaterBehaviour) RequireBlockUpdate() bool { return false }
func (b WaterBehaviour) Appearance(position itype.Vec3i, aux int, data itype.Dataset, w *world.World) world.BlockAppearance {
func (WaterBehaviour) Appearance(position itype.Vec3i, aux int, data itype.Dataset, w *world.World) world.BlockAppearance {
return world.BlockAppearance{
Name: "water",
Transparent: true,
@ -22,13 +22,13 @@ func (b WaterBehaviour) Appearance(position itype.Vec3i, aux int, data itype.Dat
aux int,
data itype.Dataset,
w *world.World,
vertexArray []world.Vertex) []world.Vertex {
vertexArray []world.Vertex, vertsWater []world.Vertex) (verts, waters []world.Vertex) {
if block := w.Block(position.Addv(0, 1, 0)); block.Id != Water {
return appendFace(itype.YPlus, position, "water.png", itype.Vec3f{0, -0.125, 0}, vertexArray)
return vertexArray, appendFace(itype.YPlus, position, "water.png", itype.Vec3f{0, -0.125, 0}, vertsWater)
}
return vertexArray
return vertexArray, vertsWater
},
}
}

View File

@ -25,7 +25,7 @@ type Chunk struct {
vao, vbo uint32
vbolen int
}
vertUpdate chan []Vertex
vertUpdate chan [2][]Vertex
world *World
}

View File

@ -34,7 +34,21 @@ func (c *Chunk) InitRender() {
gl.EnableVertexAttribArray(2)
gl.EnableVertexAttribArray(3)
c.vertUpdate = make(chan []Vertex, 2)
gl.GenVertexArrays(1, &c.water.vao)
gl.BindVertexArray(c.water.vao)
gl.GenBuffers(1, &c.water.vbo)
gl.BindBuffer(gl.ARRAY_BUFFER, c.water.vbo)
gl.VertexAttribPointer(0, 3, gl.FLOAT, false, int32(unsafe.Sizeof(Vertex{})), gl.PtrOffset(int(unsafe.Offsetof(Vertex{}.World))))
gl.VertexAttribPointer(1, 3, gl.FLOAT, false, int32(unsafe.Sizeof(Vertex{})), gl.PtrOffset(int(unsafe.Offsetof(Vertex{}.Normal))))
gl.VertexAttribPointer(2, 2, gl.FLOAT, false, int32(unsafe.Sizeof(Vertex{})), gl.PtrOffset(int(unsafe.Offsetof(Vertex{}.Texture))))
gl.VertexAttribPointer(3, 1, gl.FLOAT, false, int32(unsafe.Sizeof(Vertex{})), gl.PtrOffset(int(unsafe.Offsetof(Vertex{}.Light))))
gl.EnableVertexAttribArray(0)
gl.EnableVertexAttribArray(1)
gl.EnableVertexAttribArray(2)
gl.EnableVertexAttribArray(3)
c.vertUpdate = make(chan [2][]Vertex, 2)
c.renderChanged = true
}
@ -42,6 +56,8 @@ func (c *Chunk) InitRender() {
func (c *Chunk) FreeRender() {
gl.DeleteVertexArrays(1, &c.vao)
gl.DeleteBuffers(1, &c.vbo)
gl.DeleteVertexArrays(1, &c.water.vao)
gl.DeleteBuffers(1, &c.water.vbo)
close(c.vertUpdate)
}
@ -51,6 +67,12 @@ func (c *Chunk) Bind() {
gl.BindBuffer(gl.ARRAY_BUFFER, c.vbo)
}
// BindWater binds the semi-transparant layer of the renderer.
func (c *Chunk) BindWater() {
gl.BindVertexArray(c.water.vao)
gl.BindBuffer(gl.ARRAY_BUFFER, c.water.vbo)
}
// a global vertex array for VBO updates
//var vertex []Vertex
@ -59,17 +81,21 @@ func (c *Chunk) updateRender() {
if c.renderChanged {
go func() {
t := time.Now()
vert := c.AppendVertex([]Vertex{})
vert, vertWater := c.appendVertex([]Vertex{}, []Vertex{})
log.Printf("Chunk [%d,%d]: UpdateRender: vertex len of %d*%d = %d in %dms", c.X, c.Z, unsafe.Sizeof(Vertex{}), len(vert), int(unsafe.Sizeof(Vertex{}))*len(vert), time.Since(t).Milliseconds())
c.vertUpdate <- vert
c.vertUpdate <- [2][]Vertex{vert, vertWater}
}()
c.renderChanged = false
}
select {
case vert := <-c.vertUpdate:
gl.BufferData(gl.ARRAY_BUFFER, int(unsafe.Sizeof(Vertex{}))*len(vert), gl.Ptr(vert), gl.DYNAMIC_DRAW)
c.vbolen = len(vert)
gl.BindBuffer(gl.ARRAY_BUFFER, c.vbo)
gl.BufferData(gl.ARRAY_BUFFER, int(unsafe.Sizeof(Vertex{}))*len(vert[0]), gl.Ptr(vert[0]), gl.DYNAMIC_DRAW)
gl.BindBuffer(gl.ARRAY_BUFFER, c.water.vbo)
gl.BufferData(gl.ARRAY_BUFFER, int(unsafe.Sizeof(Vertex{}))*len(vert[1]), gl.Ptr(vert[1]), gl.DYNAMIC_DRAW)
c.vbolen = len(vert[0])
c.water.vbolen = len(vert[1])
default: // do nothing
}
}
@ -107,13 +133,23 @@ func (c *Chunk) Render() {
return
}
c.Bind()
c.updateRender()
c.Bind()
gl.DrawArrays(gl.TRIANGLES, 0, int32(c.vbolen))
}
// AppendVertex appends the chunk's global vertex into the array.
func (c *Chunk) AppendVertex(arr []Vertex) []Vertex {
func (c *Chunk) RenderWater() {
if !c.checkView(io.ViewPos, io.ViewDir) || !c.checkView(io.RenderPos, io.RenderDir) {
return
}
c.updateRender()
c.BindWater()
gl.DrawArrays(gl.TRIANGLES, 0, int32(c.water.vbolen))
}
// appendVertex appends the chunk's global vertex into the array.
func (c *Chunk) appendVertex(arr, arrwater []Vertex) (fin, finwater []Vertex) {
off := itype.Vec3i{
c.X * ChunkSizeX,
0,
@ -151,14 +187,14 @@ func (c *Chunk) AppendVertex(arr []Vertex) []Vertex {
arr = c.appendFace(itype.ZPlus, itype.Vec3i{i, j, k}, app.Name+"_z+.png", arr)
arr = c.appendFace(itype.ZMinus, itype.Vec3i{i, j, k}, app.Name+"_z-.png", arr)
case CustomRendering:
arr = app.CustomRenderAppend(off.Addv(i, j, k), int(c.Aux[i][j][k]), nil, c.world, arr)
arr, arrwater = app.CustomRenderAppend(off.Addv(i, j, k), int(c.Aux[i][j][k]), nil, c.world, arr, arrwater)
}
}
}
}
return arr
return arr, arrwater
}
func (c *Chunk) appendFace(face itype.Direction, pos itype.Vec3i, texname string, arr []Vertex) []Vertex {

View File

@ -145,3 +145,11 @@ func (w *World) Render() {
c.Render()
}
}
// RenderWater calls DrawArrays drawing the semi-transparant layer of the world.
func (w *World) RenderWater() {
for _, c := range w.Chunks {
c.RenderWater()
}
}