semi-transparent water rendering (TODO)
This commit is contained in:
parent
904221ac14
commit
fea09c5012
@ -2,23 +2,27 @@ package asset
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed shader/world.frag
|
||||
var WorldShaderFrag string
|
||||
var (
|
||||
//go:embed shader/world/output.frag
|
||||
WorldShaderFrag string
|
||||
//go:embed shader/world/output.vert
|
||||
WorldShaderVert string
|
||||
|
||||
//go:embed shader/world.vert
|
||||
var WorldShaderVert string
|
||||
//go:embed shader/world/shadowmap.frag
|
||||
WorldShaderShadowmapFrag string
|
||||
//go:embed shader/world/shadowmap.vert
|
||||
WorldShaderShadowmapVert string
|
||||
|
||||
//go:embed shader/world.shadowmap.frag
|
||||
var WorldShaderShadowmapFrag string
|
||||
//go:embed shader/world/geometry.frag
|
||||
WorldShaderGeometryFrag string
|
||||
//go:embed shader/world/geometry.vert
|
||||
WorldShaderGeometryVert string
|
||||
|
||||
//go:embed shader/world.shadowmap.vert
|
||||
var WorldShaderShadowmapVert string
|
||||
|
||||
//go:embed shader/world.geometry.frag
|
||||
var WorldShaderGeometryFrag string
|
||||
|
||||
//go:embed shader/world.geometry.vert
|
||||
var WorldShaderGeometryVert string
|
||||
//go:embed shader/world/water.frag
|
||||
WorldShaderWaterFrag string
|
||||
//go:embed shader/world/water.vert
|
||||
WorldShaderWaterVert string
|
||||
)
|
||||
|
||||
//go:embed shader/framewire.frag
|
||||
var FramewireShaderFrag string
|
||||
|
@ -24,7 +24,7 @@ out vec4 outputColor;
|
||||
|
||||
const float gamma = 2.2;
|
||||
|
||||
const float ambient = 0.3, specularStrength = 0.5, specularShininess = 32;
|
||||
const float ambient = 0.3, specularStrength = 0.08, specularShininess = 8;
|
||||
const float fogDensity = .00003;
|
||||
|
||||
|
93
internal/asset/shader/world/water.frag
Normal file
93
internal/asset/shader/world/water.frag
Normal file
@ -0,0 +1,93 @@
|
||||
#version 330
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D shadowmap;
|
||||
uniform vec3 viewPos;
|
||||
uniform vec3 sun;
|
||||
uniform vec4 fogColor;
|
||||
|
||||
uniform float alpha; // Alpha of the semi-transparant layer
|
||||
|
||||
// Fragment information
|
||||
in vec4 fragPos;
|
||||
in vec4 fragPosLightspace;
|
||||
in vec3 fragNormal;
|
||||
in vec2 fragTexCoord;
|
||||
vec4 fragColor;
|
||||
|
||||
out vec4 outputColor;
|
||||
|
||||
|
||||
const float gamma = 2.2;
|
||||
|
||||
const float ambient = 0.3, specularStrength = 1.6, specularShininess = 128;
|
||||
const float fogDensity = .00003;
|
||||
|
||||
|
||||
float finalpha;
|
||||
float light;
|
||||
vec4 texpixel, color;
|
||||
void lightSun();
|
||||
float lightSunShadow();
|
||||
void lightPoint(int i);
|
||||
|
||||
|
||||
void main() {
|
||||
|
||||
fragColor = vec4(pow(texture(tex, fragTexCoord).rgb, vec3(gamma)), 1.0f);
|
||||
|
||||
finalpha = alpha;
|
||||
light = ambient;
|
||||
|
||||
lightSun();
|
||||
|
||||
color += vec4(fragColor.rgb * light, 0.0f);
|
||||
color.a = fragColor.a;
|
||||
color.rgb = pow(color.rgb, vec3(1.0/gamma));
|
||||
|
||||
float z = gl_FragCoord.z / gl_FragCoord.w;
|
||||
float fog = clamp(exp(-fogDensity * z * z), 0.2, 1);
|
||||
|
||||
outputColor = mix(fogColor, color, fog) * finalpha;
|
||||
}
|
||||
|
||||
void lightSun() {
|
||||
/* Diffuse */
|
||||
vec3 lightDir = sun;
|
||||
float diffuse = max(dot(fragNormal, lightDir), 0.0f);
|
||||
|
||||
/* Specular */
|
||||
vec3 viewDir = normalize(viewPos - fragPos.xyz);
|
||||
vec3 reflectDir = reflect(-lightDir, fragNormal);
|
||||
float specular = specularStrength * pow(max(dot(viewDir, reflectDir), 0.0), specularShininess);
|
||||
if (specular > 1.0f) {
|
||||
finalpha = min(finalpha + specular - 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
float shadow = lightSunShadow();
|
||||
light += diffuse * shadow;
|
||||
color += vec4(vec3(specular), 0.0f) * shadow;
|
||||
finalpha = min(finalpha + 0.1f * shadow, 1.0f);
|
||||
}
|
||||
|
||||
float lightSunShadow() {
|
||||
/* Shadow */
|
||||
float bias = max(0.0013 * (1.0 - dot(fragNormal, sun)), 0.0001);
|
||||
vec3 projCoords = fragPosLightspace.xyz / fragPosLightspace.w;
|
||||
projCoords = projCoords*0.5 + 0.5;
|
||||
float closestDepth = texture(shadowmap, projCoords.xy).r;
|
||||
float currentDepth = projCoords.z;
|
||||
float shadow = 0;
|
||||
|
||||
if (currentDepth > 1.0f || currentDepth < 0.0f)
|
||||
return 1.0f;
|
||||
|
||||
//vec2 texelSize = clamp((currentDepth+bias-closestDepth)*100.0f, 0.05f, 1.5f) / textureSize(shadowmap, 0);
|
||||
vec2 texelSize = 0.4 / textureSize(shadowmap, 0);
|
||||
for (int x=-4; x<=4; ++x)
|
||||
for (int y=-4; y<=4; ++y) {
|
||||
float pcfDepth = texture(shadowmap, projCoords.xy + vec2(x,y)*texelSize).r;
|
||||
shadow += currentDepth-bias < pcfDepth ? 1.0f : 0.0f;
|
||||
}
|
||||
return min(shadow/81.0f, 1.0f);
|
||||
}
|
26
internal/asset/shader/world/water.vert
Normal file
26
internal/asset/shader/world/water.vert
Normal file
@ -0,0 +1,26 @@
|
||||
#version 330
|
||||
|
||||
uniform mat4 projection;
|
||||
uniform mat4 view;
|
||||
uniform mat4 model;
|
||||
uniform mat4 lightspace;
|
||||
|
||||
layout (location = 0) in vec3 vert;
|
||||
layout (location = 1) in vec3 normal;
|
||||
layout (location = 2) in vec2 texCoord;
|
||||
layout (location = 4) in float light;
|
||||
|
||||
out vec4 fragPos;
|
||||
out vec4 fragPosLightspace;
|
||||
out vec3 fragNormal;
|
||||
out vec2 fragTexCoord;
|
||||
|
||||
|
||||
void main() {
|
||||
fragTexCoord = texCoord;
|
||||
fragPos = model * vec4(vert, 1);
|
||||
fragPosLightspace = lightspace * fragPos;
|
||||
fragNormal = normal;
|
||||
gl_Position = projection * view * fragPos;
|
||||
}
|
||||
|
BIN
internal/entity/.physics.go.swp
Normal file
BIN
internal/entity/.physics.go.swp
Normal file
Binary file not shown.
@ -45,35 +45,6 @@ func (e *Entity) boxHitpoints(points []itype.Vec3d, hitbox itype.Boxd) []itype.V
|
||||
base.Add(itype.Vec3d{box.SizeX, 0, box.SizeZ}),
|
||||
base.Add(itype.Vec3d{box.SizeX, box.SizeY, box.SizeZ}),
|
||||
)
|
||||
/*
|
||||
// add the surface points
|
||||
// X+ and X-
|
||||
for y := base[1] + HitpointMeshLen; y < base[1]+hitbox[1]; y += HitpointMeshLen {
|
||||
for z := base[2] + HitpointMeshLen; z < base[2]+hitbox[2]; z += HitpointMeshLen {
|
||||
points = append(points,
|
||||
base.Addv(0, y, z),
|
||||
base.Addv(box.SizeX, y, z),
|
||||
)
|
||||
}
|
||||
}
|
||||
// Y+ and Y-
|
||||
for x := base[0] + HitpointMeshLen; x < base[0]+hitbox[0]; x += HitpointMeshLen {
|
||||
for z := base[2] + HitpointMeshLen; z < base[2]+hitbox[2]; z += HitpointMeshLen {
|
||||
points = append(points,
|
||||
base.Addv(x, 0, z),
|
||||
base.Addv(x, box.SizeY, z),
|
||||
)
|
||||
}
|
||||
}
|
||||
// Z+ and Z-
|
||||
for x := base[0] + HitpointMeshLen; x < base[0]+hitbox[0]; x += HitpointMeshLen {
|
||||
for y := base[1] + HitpointMeshLen; y < base[1]+hitbox[1]; y += HitpointMeshLen {
|
||||
points = append(points,
|
||||
base.Addv(x, y, 0),
|
||||
base.Addv(x, y, box.SizeZ),
|
||||
)
|
||||
}
|
||||
}*/
|
||||
return points
|
||||
}
|
||||
|
||||
@ -89,6 +60,7 @@ func pointStuck(point itype.Vec3d, w *world.World) bool {
|
||||
point.Floor(),
|
||||
block.Aux,
|
||||
block.Dataset,
|
||||
w,
|
||||
).Hitbox.Offset(blockid.ToFloat64()).Contains(point)
|
||||
}
|
||||
|
||||
@ -123,7 +95,7 @@ func (e *Entity) moveX(delta float64, hitbox itype.Boxd, w *world.World) {
|
||||
if block.Id == 0 {
|
||||
deltaDone = delta
|
||||
} else { // block.Id!=0
|
||||
app := world.GetBlockAppearance(blockid, block.Id, block.Aux, block.Dataset)
|
||||
app := world.GetBlockAppearance(blockid, block.Id, block.Aux, block.Dataset, w)
|
||||
blockBox := app.Hitbox.Offset(blockid.ToFloat64())
|
||||
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
||||
hit = true
|
||||
@ -176,7 +148,7 @@ func (e *Entity) moveY(delta float64, hitbox itype.Boxd, w *world.World) {
|
||||
if block.Id == 0 {
|
||||
deltaDone = delta
|
||||
} else { // block.Id!=0
|
||||
app := world.GetBlockAppearance(blockid, block.Id, block.Aux, block.Dataset)
|
||||
app := world.GetBlockAppearance(blockid, block.Id, block.Aux, block.Dataset, w)
|
||||
blockBox := app.Hitbox.Offset(blockid.ToFloat64())
|
||||
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
||||
hit = true
|
||||
@ -240,7 +212,7 @@ func (e *Entity) moveZ(delta float64, hitbox itype.Boxd, w *world.World) {
|
||||
if block.Id == 0 {
|
||||
deltaDone = delta
|
||||
} else { // block.Id!=0
|
||||
app := world.GetBlockAppearance(blockid, block.Id, block.Aux, block.Dataset)
|
||||
app := world.GetBlockAppearance(blockid, block.Id, block.Aux, block.Dataset, w)
|
||||
blockBox := app.Hitbox.Offset(blockid.ToFloat64())
|
||||
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
||||
hit = true
|
||||
|
@ -47,8 +47,8 @@ func (g *Game) Init(win *glfw.Window) {
|
||||
var seed int64 = time.Now().Unix()
|
||||
gensync := make(chan struct{})
|
||||
gensynccnt := 0
|
||||
for i := -8; i <= 8; i++ {
|
||||
for j := -8; j <= 8; j++ {
|
||||
for i := -4; i <= 4; i++ {
|
||||
for j := -4; j <= 4; j++ {
|
||||
c := &world.Chunk{}
|
||||
g.world.SetChunk(i, j, c)
|
||||
go func() {
|
||||
|
@ -33,6 +33,11 @@ type WorldRenderer struct {
|
||||
shader *Shader // Geometry pass shaders.
|
||||
}
|
||||
|
||||
water struct {
|
||||
fbo uint32
|
||||
shader *Shader
|
||||
}
|
||||
|
||||
shader *Shader // Deffered lighting pass shaders
|
||||
texture *Texture // World texture atlas
|
||||
}
|
||||
@ -55,16 +60,23 @@ func (r *WorldRenderer) Init(w *world.World) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.water.shader, err = NewShader(asset.WorldShaderWaterVert, asset.WorldShaderWaterFrag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
asset.InitWorldTextureAtlas()
|
||||
r.texture = NewTextureRGBA(asset.WorldTextureAtlas.Image)
|
||||
r.texture.GenerateMipMap()
|
||||
r.gbuffer.shader.SetUniformTexture("tex", r.texture)
|
||||
r.water.shader.SetUniformTexture("tex", r.texture)
|
||||
|
||||
r.depthmap.shader.SetUniformMat4("model", mgl32.Ident4())
|
||||
r.gbuffer.shader.SetUniformMat4("model", mgl32.Ident4())
|
||||
r.water.shader.SetUniformMat4("model", mgl32.Ident4())
|
||||
// and view and projection uniforms not yet set
|
||||
gl.BindFragDataLocation(r.shader.Handle(), 0, gl.Str("outputColor\x00"))
|
||||
gl.BindFragDataLocation(r.water.shader.Handle(), 0, gl.Str("outputColor\x00"))
|
||||
|
||||
// generate the depthmap and depthmap FBO
|
||||
gl.GenFramebuffers(1, &r.depthmap.fbo)
|
||||
@ -84,6 +96,7 @@ func (r *WorldRenderer) Init(w *world.World) (err error) {
|
||||
gl.ReadBuffer(gl.NONE)
|
||||
// attach the shadowmap to the shader
|
||||
r.shader.SetUniformTextureHandle("shadowmap", r.depthmap.tex)
|
||||
r.water.shader.SetUniformTextureHandle("shadowmap", r.depthmap.tex)
|
||||
|
||||
// generate G-buffer and friends
|
||||
gl.GenFramebuffers(1, &r.gbuffer.fbo)
|
||||
@ -122,6 +135,13 @@ func (r *WorldRenderer) Init(w *world.World) (err error) {
|
||||
r.shader.SetUniformTextureHandle("gNorm", r.gbuffer.norm)
|
||||
r.shader.SetUniformTextureHandle("gColor", r.gbuffer.color)
|
||||
|
||||
// generate FBO for water rendering
|
||||
gl.GenFramebuffers(1, &r.water.fbo)
|
||||
gl.BindFramebuffer(gl.FRAMEBUFFER, r.water.fbo)
|
||||
gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, r.gbuffer.depth)
|
||||
gl.DrawBuffer(gl.BACK)
|
||||
gl.ReadBuffer(gl.BACK)
|
||||
|
||||
gl.BindFramebuffer(gl.FRAMEBUFFER, 0)
|
||||
r.lastDisplaySize = io.DisplaySize
|
||||
|
||||
@ -136,6 +156,7 @@ func (r *WorldRenderer) ResizeDisplay(newSize itype.Vec2i) {
|
||||
}
|
||||
|
||||
var sun = [3]float32{0.2, 0.4, 0.3}
|
||||
var alpha float32 = 0.55
|
||||
|
||||
func (r *WorldRenderer) Render(world *world.World, view *View) {
|
||||
io.RenderPos = io.ViewPos
|
||||
@ -149,13 +170,14 @@ func (r *WorldRenderer) Render(world *world.World, view *View) {
|
||||
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA16F, int32(io.DisplaySize[0]), int32(io.DisplaySize[1]), 0, gl.RGBA, gl.FLOAT, nil)
|
||||
gl.BindTexture(gl.TEXTURE_2D, r.gbuffer.color)
|
||||
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(io.DisplaySize[0]), int32(io.DisplaySize[1]), 0, gl.RGBA, gl.UNSIGNED_BYTE, nil)
|
||||
gl.BindRenderbuffer(gl.RENDERBUFFER, r.gbuffer.norm)
|
||||
gl.BindRenderbuffer(gl.RENDERBUFFER, r.gbuffer.depth)
|
||||
gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, int32(io.DisplaySize[0]), int32(io.DisplaySize[1]))
|
||||
r.lastDisplaySize = io.DisplaySize
|
||||
}
|
||||
|
||||
imgui.SliderFloat3("Sun", &sun, -1, 1)
|
||||
normalSun := itype.Vec3f(sun).Normalize()
|
||||
imgui.SliderFloat("Water Alpha", &alpha, 0, 1)
|
||||
|
||||
gl.Enable(gl.CULL_FACE)
|
||||
gl.Enable(gl.DEPTH_TEST)
|
||||
@ -178,6 +200,7 @@ func (r *WorldRenderer) Render(world *world.World, view *View) {
|
||||
r.depthmap.shader.SetUniformMat4("lightspace", lightspace)
|
||||
|
||||
world.Render()
|
||||
world.RenderWater()
|
||||
|
||||
// 2. Geometry pass, render to G-buffer
|
||||
io.RenderPos = io.ViewPos
|
||||
@ -201,10 +224,9 @@ func (r *WorldRenderer) Render(world *world.World, view *View) {
|
||||
gl.BindFramebuffer(gl.FRAMEBUFFER, 0)
|
||||
|
||||
// 3. Render the actual output with deferred lighting
|
||||
gl.Clear(gl.DEPTH_BUFFER_BIT)
|
||||
gl.Disable(gl.DEPTH_TEST)
|
||||
r.shader.UseProgram()
|
||||
r.shader.BindTextures()
|
||||
|
||||
r.shader.SetUniformMat4("lightspace", lightspace)
|
||||
r.shader.SetUniformVec3f("viewPos", view.EyePos)
|
||||
r.shader.SetUniformVec4f("fogColor", itype.Vec4f{0.6, 0.8, 1.0, 1.0})
|
||||
@ -212,6 +234,26 @@ func (r *WorldRenderer) Render(world *world.World, view *View) {
|
||||
|
||||
DrawScreenQuad()
|
||||
|
||||
// 4. Render water
|
||||
gl.Enable(gl.DEPTH_TEST)
|
||||
gl.DepthFunc(gl.LESS)
|
||||
gl.Enable(gl.CULL_FACE)
|
||||
gl.Enable(gl.BLEND)
|
||||
gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
|
||||
gl.BlendEquation(gl.FUNC_ADD)
|
||||
gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, r.gbuffer.depth)
|
||||
r.water.shader.UseProgram()
|
||||
r.water.shader.BindTextures()
|
||||
|
||||
r.water.shader.SetUniformMat4("lightspace", lightspace)
|
||||
r.water.shader.SetUniformMat4("view", view.View())
|
||||
r.water.shader.SetUniformMat4("projection", view.Perspective())
|
||||
r.water.shader.SetUniformVec3f("viewPos", view.EyePos)
|
||||
r.water.shader.SetUniformVec3f("sun", normalSun)
|
||||
r.water.shader.SetUniformFloat("alpha", alpha)
|
||||
|
||||
world.RenderWater()
|
||||
|
||||
// Show G-buffers?
|
||||
/*if io.ShowDebugInfo {
|
||||
DrawTexture(r.gbuffer.pos, itype.Rectf{0.5, 0.5, 0.5, 0.5}, DrawTextureChannels_R|DrawTextureChannels_G|DrawTextureChannels_B, 0, 32)
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ type Chunk struct {
|
||||
vao, vbo uint32
|
||||
vbolen int
|
||||
}
|
||||
vertUpdate chan []Vertex
|
||||
vertUpdate chan [2][]Vertex
|
||||
|
||||
world *World
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user