semi-transparent water rendering (TODO)
This commit is contained in:
parent
904221ac14
commit
fea09c5012
@ -2,23 +2,27 @@ package asset
|
|||||||
|
|
||||||
import _ "embed"
|
import _ "embed"
|
||||||
|
|
||||||
//go:embed shader/world.frag
|
var (
|
||||||
var WorldShaderFrag string
|
//go:embed shader/world/output.frag
|
||||||
|
WorldShaderFrag string
|
||||||
|
//go:embed shader/world/output.vert
|
||||||
|
WorldShaderVert string
|
||||||
|
|
||||||
//go:embed shader/world.vert
|
//go:embed shader/world/shadowmap.frag
|
||||||
var WorldShaderVert string
|
WorldShaderShadowmapFrag string
|
||||||
|
//go:embed shader/world/shadowmap.vert
|
||||||
|
WorldShaderShadowmapVert string
|
||||||
|
|
||||||
//go:embed shader/world.shadowmap.frag
|
//go:embed shader/world/geometry.frag
|
||||||
var WorldShaderShadowmapFrag string
|
WorldShaderGeometryFrag string
|
||||||
|
//go:embed shader/world/geometry.vert
|
||||||
|
WorldShaderGeometryVert string
|
||||||
|
|
||||||
//go:embed shader/world.shadowmap.vert
|
//go:embed shader/world/water.frag
|
||||||
var WorldShaderShadowmapVert string
|
WorldShaderWaterFrag string
|
||||||
|
//go:embed shader/world/water.vert
|
||||||
//go:embed shader/world.geometry.frag
|
WorldShaderWaterVert string
|
||||||
var WorldShaderGeometryFrag string
|
)
|
||||||
|
|
||||||
//go:embed shader/world.geometry.vert
|
|
||||||
var WorldShaderGeometryVert string
|
|
||||||
|
|
||||||
//go:embed shader/framewire.frag
|
//go:embed shader/framewire.frag
|
||||||
var FramewireShaderFrag string
|
var FramewireShaderFrag string
|
||||||
|
@ -24,7 +24,7 @@ out vec4 outputColor;
|
|||||||
|
|
||||||
const float gamma = 2.2;
|
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;
|
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, 0, box.SizeZ}),
|
||||||
base.Add(itype.Vec3d{box.SizeX, box.SizeY, 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
|
return points
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,6 +60,7 @@ func pointStuck(point itype.Vec3d, w *world.World) bool {
|
|||||||
point.Floor(),
|
point.Floor(),
|
||||||
block.Aux,
|
block.Aux,
|
||||||
block.Dataset,
|
block.Dataset,
|
||||||
|
w,
|
||||||
).Hitbox.Offset(blockid.ToFloat64()).Contains(point)
|
).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 {
|
if block.Id == 0 {
|
||||||
deltaDone = delta
|
deltaDone = delta
|
||||||
} else { // block.Id!=0
|
} 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())
|
blockBox := app.Hitbox.Offset(blockid.ToFloat64())
|
||||||
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
||||||
hit = true
|
hit = true
|
||||||
@ -176,7 +148,7 @@ func (e *Entity) moveY(delta float64, hitbox itype.Boxd, w *world.World) {
|
|||||||
if block.Id == 0 {
|
if block.Id == 0 {
|
||||||
deltaDone = delta
|
deltaDone = delta
|
||||||
} else { // block.Id!=0
|
} 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())
|
blockBox := app.Hitbox.Offset(blockid.ToFloat64())
|
||||||
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
||||||
hit = true
|
hit = true
|
||||||
@ -240,7 +212,7 @@ func (e *Entity) moveZ(delta float64, hitbox itype.Boxd, w *world.World) {
|
|||||||
if block.Id == 0 {
|
if block.Id == 0 {
|
||||||
deltaDone = delta
|
deltaDone = delta
|
||||||
} else { // block.Id!=0
|
} 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())
|
blockBox := app.Hitbox.Offset(blockid.ToFloat64())
|
||||||
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
if !app.NotSolid && blockBox.Contains(dest) { // Hit!
|
||||||
hit = true
|
hit = true
|
||||||
|
@ -47,8 +47,8 @@ func (g *Game) Init(win *glfw.Window) {
|
|||||||
var seed int64 = time.Now().Unix()
|
var seed int64 = time.Now().Unix()
|
||||||
gensync := make(chan struct{})
|
gensync := make(chan struct{})
|
||||||
gensynccnt := 0
|
gensynccnt := 0
|
||||||
for i := -8; i <= 8; i++ {
|
for i := -4; i <= 4; i++ {
|
||||||
for j := -8; j <= 8; j++ {
|
for j := -4; j <= 4; j++ {
|
||||||
c := &world.Chunk{}
|
c := &world.Chunk{}
|
||||||
g.world.SetChunk(i, j, c)
|
g.world.SetChunk(i, j, c)
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -33,6 +33,11 @@ type WorldRenderer struct {
|
|||||||
shader *Shader // Geometry pass shaders.
|
shader *Shader // Geometry pass shaders.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
water struct {
|
||||||
|
fbo uint32
|
||||||
|
shader *Shader
|
||||||
|
}
|
||||||
|
|
||||||
shader *Shader // Deffered lighting pass shaders
|
shader *Shader // Deffered lighting pass shaders
|
||||||
texture *Texture // World texture atlas
|
texture *Texture // World texture atlas
|
||||||
}
|
}
|
||||||
@ -55,16 +60,23 @@ func (r *WorldRenderer) Init(w *world.World) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
r.water.shader, err = NewShader(asset.WorldShaderWaterVert, asset.WorldShaderWaterFrag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
asset.InitWorldTextureAtlas()
|
asset.InitWorldTextureAtlas()
|
||||||
r.texture = NewTextureRGBA(asset.WorldTextureAtlas.Image)
|
r.texture = NewTextureRGBA(asset.WorldTextureAtlas.Image)
|
||||||
r.texture.GenerateMipMap()
|
r.texture.GenerateMipMap()
|
||||||
r.gbuffer.shader.SetUniformTexture("tex", r.texture)
|
r.gbuffer.shader.SetUniformTexture("tex", r.texture)
|
||||||
|
r.water.shader.SetUniformTexture("tex", r.texture)
|
||||||
|
|
||||||
r.depthmap.shader.SetUniformMat4("model", mgl32.Ident4())
|
r.depthmap.shader.SetUniformMat4("model", mgl32.Ident4())
|
||||||
r.gbuffer.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
|
// and view and projection uniforms not yet set
|
||||||
gl.BindFragDataLocation(r.shader.Handle(), 0, gl.Str("outputColor\x00"))
|
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
|
// generate the depthmap and depthmap FBO
|
||||||
gl.GenFramebuffers(1, &r.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)
|
gl.ReadBuffer(gl.NONE)
|
||||||
// attach the shadowmap to the shader
|
// attach the shadowmap to the shader
|
||||||
r.shader.SetUniformTextureHandle("shadowmap", r.depthmap.tex)
|
r.shader.SetUniformTextureHandle("shadowmap", r.depthmap.tex)
|
||||||
|
r.water.shader.SetUniformTextureHandle("shadowmap", r.depthmap.tex)
|
||||||
|
|
||||||
// generate G-buffer and friends
|
// generate G-buffer and friends
|
||||||
gl.GenFramebuffers(1, &r.gbuffer.fbo)
|
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("gNorm", r.gbuffer.norm)
|
||||||
r.shader.SetUniformTextureHandle("gColor", r.gbuffer.color)
|
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)
|
gl.BindFramebuffer(gl.FRAMEBUFFER, 0)
|
||||||
r.lastDisplaySize = io.DisplaySize
|
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 sun = [3]float32{0.2, 0.4, 0.3}
|
||||||
|
var alpha float32 = 0.55
|
||||||
|
|
||||||
func (r *WorldRenderer) Render(world *world.World, view *View) {
|
func (r *WorldRenderer) Render(world *world.World, view *View) {
|
||||||
io.RenderPos = io.ViewPos
|
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.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.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.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]))
|
gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, int32(io.DisplaySize[0]), int32(io.DisplaySize[1]))
|
||||||
r.lastDisplaySize = io.DisplaySize
|
r.lastDisplaySize = io.DisplaySize
|
||||||
}
|
}
|
||||||
|
|
||||||
imgui.SliderFloat3("Sun", &sun, -1, 1)
|
imgui.SliderFloat3("Sun", &sun, -1, 1)
|
||||||
normalSun := itype.Vec3f(sun).Normalize()
|
normalSun := itype.Vec3f(sun).Normalize()
|
||||||
|
imgui.SliderFloat("Water Alpha", &alpha, 0, 1)
|
||||||
|
|
||||||
gl.Enable(gl.CULL_FACE)
|
gl.Enable(gl.CULL_FACE)
|
||||||
gl.Enable(gl.DEPTH_TEST)
|
gl.Enable(gl.DEPTH_TEST)
|
||||||
@ -178,6 +200,7 @@ func (r *WorldRenderer) Render(world *world.World, view *View) {
|
|||||||
r.depthmap.shader.SetUniformMat4("lightspace", lightspace)
|
r.depthmap.shader.SetUniformMat4("lightspace", lightspace)
|
||||||
|
|
||||||
world.Render()
|
world.Render()
|
||||||
|
world.RenderWater()
|
||||||
|
|
||||||
// 2. Geometry pass, render to G-buffer
|
// 2. Geometry pass, render to G-buffer
|
||||||
io.RenderPos = io.ViewPos
|
io.RenderPos = io.ViewPos
|
||||||
@ -201,10 +224,9 @@ func (r *WorldRenderer) Render(world *world.World, view *View) {
|
|||||||
gl.BindFramebuffer(gl.FRAMEBUFFER, 0)
|
gl.BindFramebuffer(gl.FRAMEBUFFER, 0)
|
||||||
|
|
||||||
// 3. Render the actual output with deferred lighting
|
// 3. Render the actual output with deferred lighting
|
||||||
gl.Clear(gl.DEPTH_BUFFER_BIT)
|
gl.Disable(gl.DEPTH_TEST)
|
||||||
r.shader.UseProgram()
|
r.shader.UseProgram()
|
||||||
r.shader.BindTextures()
|
r.shader.BindTextures()
|
||||||
|
|
||||||
r.shader.SetUniformMat4("lightspace", lightspace)
|
r.shader.SetUniformMat4("lightspace", lightspace)
|
||||||
r.shader.SetUniformVec3f("viewPos", view.EyePos)
|
r.shader.SetUniformVec3f("viewPos", view.EyePos)
|
||||||
r.shader.SetUniformVec4f("fogColor", itype.Vec4f{0.6, 0.8, 1.0, 1.0})
|
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()
|
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?
|
// Show G-buffers?
|
||||||
/*if io.ShowDebugInfo {
|
/*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)
|
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,
|
data itype.Dataset,
|
||||||
world *World,
|
world *World,
|
||||||
vertexArray []Vertex,
|
vertexArray []Vertex,
|
||||||
) []Vertex
|
vertexArrayWater []Vertex,
|
||||||
|
) (verts []Vertex, waters []Vertex)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockBehaviour describes a kind of block of the same Major ID.
|
// 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) Static() bool { return false }
|
||||||
func (WaterBehaviour) RequireDataset() bool { return false }
|
func (WaterBehaviour) RequireDataset() bool { return false }
|
||||||
func (WaterBehaviour) RequireBlockUpdate() 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{
|
return world.BlockAppearance{
|
||||||
Name: "water",
|
Name: "water",
|
||||||
Transparent: true,
|
Transparent: true,
|
||||||
@ -22,13 +22,13 @@ func (b WaterBehaviour) Appearance(position itype.Vec3i, aux int, data itype.Dat
|
|||||||
aux int,
|
aux int,
|
||||||
data itype.Dataset,
|
data itype.Dataset,
|
||||||
w *world.World,
|
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 {
|
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
|
vao, vbo uint32
|
||||||
vbolen int
|
vbolen int
|
||||||
}
|
}
|
||||||
vertUpdate chan []Vertex
|
vertUpdate chan [2][]Vertex
|
||||||
|
|
||||||
world *World
|
world *World
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,21 @@ func (c *Chunk) InitRender() {
|
|||||||
gl.EnableVertexAttribArray(2)
|
gl.EnableVertexAttribArray(2)
|
||||||
gl.EnableVertexAttribArray(3)
|
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
|
c.renderChanged = true
|
||||||
}
|
}
|
||||||
@ -42,6 +56,8 @@ func (c *Chunk) InitRender() {
|
|||||||
func (c *Chunk) FreeRender() {
|
func (c *Chunk) FreeRender() {
|
||||||
gl.DeleteVertexArrays(1, &c.vao)
|
gl.DeleteVertexArrays(1, &c.vao)
|
||||||
gl.DeleteBuffers(1, &c.vbo)
|
gl.DeleteBuffers(1, &c.vbo)
|
||||||
|
gl.DeleteVertexArrays(1, &c.water.vao)
|
||||||
|
gl.DeleteBuffers(1, &c.water.vbo)
|
||||||
close(c.vertUpdate)
|
close(c.vertUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +67,12 @@ func (c *Chunk) Bind() {
|
|||||||
gl.BindBuffer(gl.ARRAY_BUFFER, c.vbo)
|
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
|
// a global vertex array for VBO updates
|
||||||
//var vertex []Vertex
|
//var vertex []Vertex
|
||||||
|
|
||||||
@ -59,17 +81,21 @@ func (c *Chunk) updateRender() {
|
|||||||
if c.renderChanged {
|
if c.renderChanged {
|
||||||
go func() {
|
go func() {
|
||||||
t := time.Now()
|
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())
|
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
|
c.renderChanged = false
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case vert := <-c.vertUpdate:
|
case vert := <-c.vertUpdate:
|
||||||
gl.BufferData(gl.ARRAY_BUFFER, int(unsafe.Sizeof(Vertex{}))*len(vert), gl.Ptr(vert), gl.DYNAMIC_DRAW)
|
gl.BindBuffer(gl.ARRAY_BUFFER, c.vbo)
|
||||||
c.vbolen = len(vert)
|
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
|
default: // do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,13 +133,23 @@ func (c *Chunk) Render() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Bind()
|
|
||||||
c.updateRender()
|
c.updateRender()
|
||||||
|
c.Bind()
|
||||||
gl.DrawArrays(gl.TRIANGLES, 0, int32(c.vbolen))
|
gl.DrawArrays(gl.TRIANGLES, 0, int32(c.vbolen))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendVertex appends the chunk's global vertex into the array.
|
func (c *Chunk) RenderWater() {
|
||||||
func (c *Chunk) AppendVertex(arr []Vertex) []Vertex {
|
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{
|
off := itype.Vec3i{
|
||||||
c.X * ChunkSizeX,
|
c.X * ChunkSizeX,
|
||||||
0,
|
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.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)
|
arr = c.appendFace(itype.ZMinus, itype.Vec3i{i, j, k}, app.Name+"_z-.png", arr)
|
||||||
case CustomRendering:
|
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 {
|
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()
|
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