From 892570a442a38213e94e877e234a090e92cef61d Mon Sep 17 00:00:00 2001 From: TomTheFurry Date: Fri, 15 Apr 2022 18:25:58 +0800 Subject: [PATCH] Add curve shader + fix/change ibo upload --- .../bufferBuilding/BufferQuad.java | 7 +- .../lod/core/render/LodRenderProgram.java | 6 ++ .../lod/core/render/objects/GLBuffer.java | 1 + .../render/objects/QuadElementBuffer.java | 13 ++-- src/main/resources/shaders/curve.vert | 76 +++++++++++++++++++ 5 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 src/main/resources/shaders/curve.vert diff --git a/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/BufferQuad.java b/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/BufferQuad.java index 5b8131c8f..e590edc8a 100644 --- a/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/BufferQuad.java +++ b/src/main/java/com/seibel/lod/core/builders/lodBuilding/bufferBuilding/BufferQuad.java @@ -227,8 +227,11 @@ public class BufferQuad thisParallelCompareWidth = this.widthEastWest; otherParallelCompareWidth = quad.widthEastWest; } - - + + // TEMP: Hard limit for width + if (thisPerpendicularCompareWidth >= 8) return false; + if (Math.floorDiv(otherPerpendicularCompareStartPos, 8) + != Math.floorDiv(thisPerpendicularCompareStartPos, 8)) return false; // check if these quads are adjacent if (thisPerpendicularCompareStartPos + thisPerpendicularCompareWidth < otherPerpendicularCompareStartPos || diff --git a/src/main/java/com/seibel/lod/core/render/LodRenderProgram.java b/src/main/java/com/seibel/lod/core/render/LodRenderProgram.java index 1af94793b..b32be7767 100644 --- a/src/main/java/com/seibel/lod/core/render/LodRenderProgram.java +++ b/src/main/java/com/seibel/lod/core/render/LodRenderProgram.java @@ -42,6 +42,8 @@ public class LodRenderProgram extends ShaderProgram { public final int mircoOffsetUniform; + public final int earthRadiusUniform; + public final int lightMapUniform; // Fog Uniforms public final int fogColorUniform; @@ -64,6 +66,7 @@ public class LodRenderProgram extends ShaderProgram { modelOffsetUniform = getUniformLocation("modelOffset"); worldYOffsetUniform = tryGetUniformLocation("worldYOffset"); mircoOffsetUniform = getUniformLocation("mircoOffset"); + earthRadiusUniform = tryGetUniformLocation("earthRadius"); lightMapUniform = getUniformLocation("lightMap"); @@ -141,6 +144,9 @@ public class LodRenderProgram extends ShaderProgram { setUniform(lightMapUniform, lightmapBindPoint); if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float)worldYOffset); + if (earthRadiusUniform != -1) setUniform(earthRadiusUniform, + 63710f); //radio of 1 to 100 to Earth radius (6,371 KM) + // (float)lodDrawDistance); // Fog setUniform(fullFogModeUniform, fullFogMode ? 1 : 0); diff --git a/src/main/java/com/seibel/lod/core/render/objects/GLBuffer.java b/src/main/java/com/seibel/lod/core/render/objects/GLBuffer.java index 87665a414..2916b637b 100644 --- a/src/main/java/com/seibel/lod/core/render/objects/GLBuffer.java +++ b/src/main/java/com/seibel/lod/core/render/objects/GLBuffer.java @@ -157,6 +157,7 @@ public class GLBuffer implements AutoCloseable { GL32.glDeleteBuffers(id); id = GL32.glGenBuffers(); GL32.glBindBuffer(getBufferBindingTarget(), id); + GL32.glBindBuffer(getBufferBindingTarget(), id); GL44.glBufferStorage(getBufferBindingTarget(), newSize, bufferHint); } else { GL32.glBufferData(GL32.GL_ARRAY_BUFFER, newSize, bufferHint); diff --git a/src/main/java/com/seibel/lod/core/render/objects/QuadElementBuffer.java b/src/main/java/com/seibel/lod/core/render/objects/QuadElementBuffer.java index 99eca5f60..9844c3068 100644 --- a/src/main/java/com/seibel/lod/core/render/objects/QuadElementBuffer.java +++ b/src/main/java/com/seibel/lod/core/render/objects/QuadElementBuffer.java @@ -90,6 +90,7 @@ public class QuadElementBuffer extends GLElementBuffer { if (quadCount < 0) { throw new IllegalArgumentException("quadCount must be greater than 0"); } + if (quadCount == 0) return; // FIXME: This doesn't happens yet, but just add this since everything will break if it does indicesCount = quadCount * 6; // 2 triangles per quad if (indicesCount >= getCapacity() && indicesCount < getCapacity() * BUFFER_SHRINK_TRIGGER) { return; @@ -107,17 +108,15 @@ public class QuadElementBuffer extends GLElementBuffer { ApiShared.LOGGER.info("Quad IBO Resizing from [" + getCapacity() + "] to [" + quadCount + "]" + " with type: " + GLEnums.getString(type)); - ByteBuffer buffer; + ByteBuffer buffer = ByteBuffer.allocateDirect(indicesCount * GLEnums.getTypeSize(type)).order(ByteOrder.nativeOrder()); + buildBuffer(quadCount, buffer, type); if (!gl.bufferStorageSupported) { + bind(); - buffer = super.mapBuffer(indicesCount * GLEnums.getTypeSize(type), GpuUploadMethod.BUFFER_MAPPING, - indicesCount * GLEnums.getTypeSize(type), GL32.GL_STATIC_DRAW, - GL32.GL_MAP_WRITE_BIT | GL32.GL_MAP_INVALIDATE_BUFFER_BIT | GL32.GL_MAP_UNSYNCHRONIZED_BIT); - buildBuffer(quadCount, buffer, type); + super.uploadBuffer(buffer, GpuUploadMethod.DATA, + indicesCount * GLEnums.getTypeSize(type), GL32.GL_STATIC_DRAW); super.unmapBuffer(); } else { - buffer = ByteBuffer.allocateDirect(indicesCount * GLEnums.getTypeSize(type)).order(ByteOrder.nativeOrder()); - buildBuffer(quadCount, buffer, type); bind(); super.uploadBuffer(buffer, GpuUploadMethod.BUFFER_STORAGE, indicesCount * GLEnums.getTypeSize(type), 0); diff --git a/src/main/resources/shaders/curve.vert b/src/main/resources/shaders/curve.vert new file mode 100644 index 000000000..6a2d024cc --- /dev/null +++ b/src/main/resources/shaders/curve.vert @@ -0,0 +1,76 @@ +#version 150 core + +in uvec4 vPosition; +in vec4 color; + +out vec4 vertexColor; +out vec3 vertexWorldPos; +out float vertexYPos; + +uniform mat4 combinedMatrix; +uniform vec3 modelOffset; +uniform float worldYOffset; + +uniform int worldSkyLight; +uniform sampler2D lightMap; +uniform float mircoOffset; + +uniform float earthRadius; + +/** + * Vertex Shader + * + * author: James Seibel + * version: 12-8-2021 + * + * updated: TomTheFurry + * version: 15-2-2022 + */ +void main() +{ + vertexWorldPos = vPosition.xyz + modelOffset; + + vertexYPos = vPosition.y + worldYOffset; + + uint meta = vPosition.a; + + uint mirco = (meta & 0xFF00u) >> 8u; // mirco offset which is a xyz 2bit value + // 0b00 = no offset + // 0b01 = positive offset + // 0b11 = negative offset + // format is: 0b00zzyyxx + float mx = (mirco & 1u)!=0u ? mircoOffset : 0.0; + mx = (mirco & 2u)!=0u ? -mx : mx; + float my = (mirco & 4u)!=0u ? mircoOffset : 0.0; + my = (mirco & 8u)!=0u ? -my : my; + float mz = (mirco & 16u)!=0u ? mircoOffset : 0.0; + mz = (mirco & 32u)!=0u ? -mz : mz; + vertexWorldPos.x += mx; + vertexWorldPos.y += my; + vertexWorldPos.z += mz; + + // Calculate the vertex pos due to curvature of the earth + // We use spherical coordinates to calculate the vertex position + if (vertexWorldPos.x == 0.0 && vertexWorldPos.z == 0.0) + { + // In the center. No curvature needed + } + else + { + float theta = atan(vertexWorldPos.z, vertexWorldPos.x); // in radians (-pi, pi) + float trueY = earthRadius + vertexWorldPos.y; // true Y position, or height + float phi = sqrt(vertexWorldPos.z * vertexWorldPos.z + vertexWorldPos.x * vertexWorldPos.x) / trueY; + // Convert spherical coordinates to cartesian coordinates + vertexWorldPos.x = trueY * sin(phi) * cos(theta); + vertexWorldPos.z = trueY * sin(phi) * sin(theta); + vertexWorldPos.y = trueY * cos(phi) - earthRadius; + } + + uint lights = meta & 0xFFu; + + float light2 = (mod(float(lights), 16.0)+0.5) / 16.0; + float light = (float(lights/16u)+0.5) / 16.0; + vertexColor = color * vec4(texture(lightMap, vec2(light, light2)).xyz, 1.0); + + gl_Position = combinedMatrix * vec4(vertexWorldPos, 1.0); +}