diff --git a/src/main/java/de/bixilon/minosoft/config/config/game/entities/EntityHitBoxConfig.kt b/src/main/java/de/bixilon/minosoft/config/config/game/entities/EntityHitBoxConfig.kt index 0afd53f24..cdb91e1df 100644 --- a/src/main/java/de/bixilon/minosoft/config/config/game/entities/EntityHitBoxConfig.kt +++ b/src/main/java/de/bixilon/minosoft/config/config/game/entities/EntityHitBoxConfig.kt @@ -20,4 +20,5 @@ data class EntityHitBoxConfig( @Json(name = "own_hit_box") val ownHitBox: Boolean = false, @Json(name = "disable_z_buffer") val disableZBuffer: Boolean = false, @Json(name = "invisible_entities") val invisibleEntities: Boolean = false, + @Json(name = "lazy_hit_boxes") val lazyHitBoxes: Boolean = false, ) diff --git a/src/main/java/de/bixilon/minosoft/data/entities/EntityRotation.kt b/src/main/java/de/bixilon/minosoft/data/entities/EntityRotation.kt index a5f90e43c..921b9d3a1 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/EntityRotation.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/EntityRotation.kt @@ -12,10 +12,21 @@ */ package de.bixilon.minosoft.data.entities +import glm_.func.cos +import glm_.func.rad +import glm_.func.sin +import glm_.vec3.Vec3d + data class EntityRotation( val yaw: Double, val pitch: Double, ) { + val front: Vec3d + get() = Vec3d( + (yaw + 90).rad.cos * (-pitch).rad.cos, + (-pitch).rad.sin, + (yaw + 90).rad.sin * (-pitch).rad.cos + ).normalize() constructor(bodyYaw: Float, pitch: Float) : this(bodyYaw.toDouble(), pitch.toDouble()) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/EntityHitBox.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/EntityHitBox.kt index 2b12b57e7..598cddb4d 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/EntityHitBox.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/EntityHitBox.kt @@ -25,9 +25,6 @@ import de.bixilon.minosoft.gui.rendering.util.VecUtil.empty import de.bixilon.minosoft.gui.rendering.util.mesh.LineMesh import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY -import glm_.func.cos -import glm_.func.rad -import glm_.func.sin import glm_.vec3.Vec3 import glm_.vec3.Vec3d @@ -72,7 +69,11 @@ class EntityHitBox( } if (visible) { val mesh = LineMesh(renderWindow) - mesh.drawAABB(aabb = aabb, color = hitBoxColor) + if (Minosoft.config.config.game.entities.hitBox.lazyHitBoxes) { + mesh.drawLazyAABB(aabb, color = hitBoxColor) + } else { + mesh.drawAABB(aabb = aabb, color = hitBoxColor, margin = 0.1f) + } val center = Vec3(aabb.center) if (!velocity.empty) { @@ -85,15 +86,9 @@ class EntityHitBox( mesh.drawAABB(eyeAABB, RenderConstants.DEFAULT_LINE_WIDTH, ChatColors.DARK_RED) - val front = Vec3d( - (rotation.yaw + 90).rad.cos * (-rotation.pitch).rad.cos, - (-rotation.pitch).rad.sin, - (rotation.yaw + 90).rad.sin * (-rotation.pitch).rad.cos - ).normalize() - val eyeStart = Vec3(center.x, eyeHeight, center.z) - mesh.drawLine(eyeStart, eyeStart + Vec3(front) * 5, color = ChatColors.BLUE) + mesh.drawLine(eyeStart, eyeStart + Vec3(rotation.front) * 5, color = ChatColors.BLUE) mesh.load() this.mesh = mesh } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt index 368afdeb9..78248a6b8 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt @@ -46,9 +46,7 @@ import de.bixilon.minosoft.util.KUtil import de.bixilon.minosoft.util.KUtil.decide import de.bixilon.minosoft.util.KUtil.toResourceLocation import de.bixilon.minosoft.util.Previous -import glm_.func.cos import glm_.func.rad -import glm_.func.sin import glm_.glm import glm_.mat4x4.Mat4 import glm_.mat4x4.Mat4d @@ -123,8 +121,9 @@ class Camera( } yaw %= 180 val pitch = glm.clamp(delta.y + connection.player.rotation.pitch, -89.9, 89.9) - connection.player.rotation = EntityRotation(yaw, pitch) - setRotation(yaw, pitch) + val rotation = EntityRotation(yaw, pitch) + connection.player.rotation = rotation + setRotation(rotation) } private fun calculateFogDistance() { @@ -273,7 +272,7 @@ class Camera( } private fun onPositionChange() { - setRotation(connection.player.rotation.yaw, connection.player.rotation.pitch) + setRotation(connection.player.rotation) recalculateViewProjectionMatrix() frustum.recalculate() connection.fireEvent(FrustumChangeEvent(renderWindow, frustum)) @@ -310,12 +309,8 @@ class Camera( return glm.lookAt(eyePosition, eyePosition + cameraFront, CAMERA_UP_VEC3) } - private fun setRotation(yaw: Double, pitch: Double) { - cameraFront = Vec3d( - (yaw + 90).rad.cos * (-pitch).rad.cos, - (-pitch).rad.sin, - (yaw + 90).rad.sin * (-pitch).rad.cos - ).normalize() + private fun setRotation(rotation: EntityRotation) { + cameraFront = rotation.front cameraRight = (cameraFront cross CAMERA_UP_VEC3).normalize() cameraUp = (cameraRight cross cameraFront).normalize() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleMesh.kt index 18a519c3d..255da8100 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleMesh.kt @@ -14,7 +14,6 @@ package de.bixilon.minosoft.gui.rendering.particle import de.bixilon.minosoft.data.text.RGBColor -import de.bixilon.minosoft.gui.rendering.RenderConstants import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.system.base.buffer.vertex.PrimitiveTypes import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture @@ -27,22 +26,30 @@ import glm_.vec3.Vec3d class ParticleMesh(renderWindow: RenderWindow, data: DirectArrayFloatList) : Mesh(renderWindow, ParticleMeshStruct, PrimitiveTypes.POINT, -1, clearOnLoad = false, data = data) { - fun addVertex(position: Vec3d, scale: Float, texture: AbstractTexture, tintColor: RGBColor, uvMin: Vec2 = Vec2(0.0f, 0.0f), uvMax: Vec2 = Vec2(1.0f, 1.0f)) { - val minTransformedUV = texture.renderData?.transformUV(uvMin) ?: uvMin - val maxTransformedUV = texture.renderData?.transformUV(uvMax) ?: uvMax + fun addVertex(position: Vec3d, scale: Float, texture: AbstractTexture, tintColor: RGBColor, uvMin: FloatArray? = null, uvMax: FloatArray? = null) { + val minTransformedUV = if (uvMin == null) { + EMPTY_UV_ARRAY + } else { + texture.renderData.transformUV(uvMin) + } + val maxTransformedUV = texture.renderData.transformUV(uvMax) data.add(position.x.toFloat()) data.add(position.y.toFloat()) data.add(position.z.toFloat()) - data.add(minTransformedUV.x) - data.add(minTransformedUV.y) - data.add(maxTransformedUV.x) - data.add(maxTransformedUV.y) - data.add(Float.fromBits(texture.renderData?.shaderTextureId ?: RenderConstants.DEBUG_TEXTURE_ID)) + data.add(minTransformedUV[0]) + data.add(minTransformedUV[1]) + data.add(maxTransformedUV[0]) + data.add(maxTransformedUV[1]) + data.add(Float.fromBits(texture.renderData.shaderTextureId)) data.add(scale) data.add(Float.fromBits(tintColor.rgba)) } + companion object { + private val EMPTY_UV_ARRAY = floatArrayOf(0.0f, 0.0f) + } + data class ParticleMeshStruct( val position: Vec3, val minUVCoordinates: Vec2, diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleRenderer.kt index bc27c4d52..5cb1cd48b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleRenderer.kt @@ -15,10 +15,7 @@ package de.bixilon.minosoft.gui.rendering.particle import de.bixilon.minosoft.Minosoft import de.bixilon.minosoft.data.registries.ResourceLocation -import de.bixilon.minosoft.gui.rendering.RenderConstants -import de.bixilon.minosoft.gui.rendering.RenderWindow -import de.bixilon.minosoft.gui.rendering.Renderer -import de.bixilon.minosoft.gui.rendering.RendererBuilder +import de.bixilon.minosoft.gui.rendering.* import de.bixilon.minosoft.gui.rendering.modding.events.CameraMatrixChangeEvent import de.bixilon.minosoft.gui.rendering.particle.types.Particle import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem @@ -55,9 +52,9 @@ class ParticleRenderer( private var translucentMesh = ParticleMesh(renderWindow, DirectArrayFloatList(RenderConstants.MAXIMUM_PARTICLE_AMOUNT * ParticleMesh.ParticleMeshStruct.FLOATS_PER_VERTEX)) private val particlesLock = ReadWriteLock() - private var particles: MutableSet = mutableSetOf() + private var particles: MutableList = mutableListOf() private var particleQueueLock = ReadWriteLock() - private var particleQueue: MutableSet = mutableSetOf() + private var particleQueue: MutableList = mutableListOf() private lateinit var particleTask: TimeWorkerTask @@ -107,19 +104,38 @@ class ParticleRenderer( connection.world.particleRenderer = this particleTask = TimeWorker.addTask(TimeWorkerTask(ProtocolDefinition.TICK_TIME, maxDelayTime = ProtocolDefinition.TICK_TIME / 2) { + if (renderWindow.renderingState == RenderingStates.PAUSED || renderWindow.renderingState == RenderingStates.STOPPED) { + return@TimeWorkerTask + } + val cameraLength = connection.player.position.length() + val toRemove: MutableSet = mutableSetOf() + particlesLock.acquire() try { val time = KUtil.time for (particle in particles) { if (particle.position.length() - cameraLength >= Minosoft.config.config.game.camera.viewDistance * ProtocolDefinition.SECTION_WIDTH_X) { particle.dead = true + toRemove += particle + } else if (particle.dead) { + toRemove += particle } particle.tryTick(time) } } finally { particlesLock.release() } + + particlesLock.lock() + particles -= toRemove + + particleQueueLock.lock() + particles += particleQueue + particleQueue.clear() + particleQueueLock.unlock() + + particlesLock.unlock() }) connection.registerEvent(CallbackEventInvoker.of { @@ -131,6 +147,9 @@ class ParticleRenderer( } fun add(particle: Particle) { + if (renderWindow.renderingState == RenderingStates.PAUSED || renderWindow.renderingState == RenderingStates.STOPPED) { + return + } val particleCount = particles.size if (particleCount >= RenderConstants.MAXIMUM_PARTICLE_AMOUNT) { Log.log(LogMessageType.RENDERING_GENERAL, LogLevels.WARN) { "Can not add particle: Limit reached (${particleCount} > ${RenderConstants.MAXIMUM_PARTICLE_AMOUNT}" } @@ -154,26 +173,17 @@ class ParticleRenderer( transparentMesh.unload() translucentMesh.unload() - val toRemove: MutableSet = mutableSetOf() transparentMesh.data.clear() translucentMesh.data.clear() transparentMesh = ParticleMesh(renderWindow, transparentMesh.data) translucentMesh = ParticleMesh(renderWindow, translucentMesh.data) - - particlesLock.lock() - particleQueueLock.acquire() - particles += particleQueue - particleQueueLock.release() - particlesLock.unlock() - particlesLock.acquire() val time = KUtil.time for (particle in particles) { if (particle.dead) { - toRemove += particle continue } particle.addVertex(transparentMesh, translucentMesh, time) @@ -181,12 +191,6 @@ class ParticleRenderer( particlesLock.release() - if (toRemove.isNotEmpty()) { - particlesLock.lock() - particles -= toRemove - particlesLock.unlock() - } - transparentMesh.load() translucentMesh.load() } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/advanced/AdvancedTextureParticle.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/advanced/AdvancedTextureParticle.kt index 9a29c22ce..e4384f32e 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/advanced/AdvancedTextureParticle.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/advanced/AdvancedTextureParticle.kt @@ -25,11 +25,11 @@ abstract class AdvancedTextureParticle(connection: PlayConnection, position: Vec var minUV: Vec2 = Vec2(0.0f, 0.0f) var maxUV: Vec2 = Vec2(1.0f, 1.0f) - override fun addVertex(transparentMesh: ParticleMesh, translucentMesh: ParticleMesh, time:Long) { + override fun addVertex(transparentMesh: ParticleMesh, particleMesh: ParticleMesh, time: Long) { val texture = texture ?: return when { - texture.transparency == TextureTransparencies.TRANSLUCENT || color.alpha != 255 -> translucentMesh + texture.transparency == TextureTransparencies.TRANSLUCENT || color.alpha != 255 -> particleMesh else -> transparentMesh - }.addVertex(getCameraPosition(time), scale, texture, color, minUV, maxUV) + }.addVertex(getCameraPosition(time), scale, texture, color, minUV.array, maxUV.array) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/AbstractTexture.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/AbstractTexture.kt index 6dc6a551b..eabbee5ef 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/AbstractTexture.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/AbstractTexture.kt @@ -35,7 +35,7 @@ interface AbstractTexture { val transparency: TextureTransparencies var properties: ImageProperties - var renderData: TextureRenderData? + var renderData: TextureRenderData var data: ByteBuffer? diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/MemoryTexture.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/MemoryTexture.kt index 525e437a7..42579ae29 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/MemoryTexture.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/MemoryTexture.kt @@ -33,7 +33,7 @@ class MemoryTexture( ) : AbstractTexture { override lateinit var textureArrayUV: Vec2 override lateinit var singlePixelSize: Vec2 - override var renderData: TextureRenderData? = null + override lateinit var renderData: TextureRenderData override var transparency: TextureTransparencies = TextureTransparencies.OPAQUE private set override var data: ByteBuffer? = null diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/PNGTexture.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/PNGTexture.kt index 2f00c4c16..4a35d0f92 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/PNGTexture.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/PNGTexture.kt @@ -26,7 +26,7 @@ import java.nio.ByteBuffer class PNGTexture(override val resourceLocation: ResourceLocation) : AbstractTexture { - override var renderData: TextureRenderData? = null + override lateinit var renderData: TextureRenderData override lateinit var textureArrayUV: Vec2 override lateinit var singlePixelSize: Vec2 diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/SpriteTexture.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/SpriteTexture.kt index b15e0c260..b9e6af9e3 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/SpriteTexture.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/SpriteTexture.kt @@ -28,7 +28,7 @@ class SpriteTexture(private val original: AbstractTexture) : AbstractTexture { override var textureArrayUV: Vec2 by original::textureArrayUV override var singlePixelSize: Vec2 by original::singlePixelSize override var properties: ImageProperties by original::properties - override var renderData: TextureRenderData? by original::renderData + override var renderData: TextureRenderData by original::renderData override val transparency: TextureTransparencies by original::transparency override var state: TextureStates = TextureStates.DECLARED diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/TextureRenderData.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/TextureRenderData.kt index d71c06d8d..bd79d63b8 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/TextureRenderData.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/TextureRenderData.kt @@ -19,5 +19,6 @@ interface TextureRenderData { val shaderTextureId: Int val animationData: Int - fun transformUV(end: Vec2): Vec2 + fun transformUV(end: Vec2?): Vec2 + fun transformUV(end: FloatArray?): FloatArray } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/texture/OpenGLTextureData.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/texture/OpenGLTextureData.kt index 08f5e9376..4fec492a3 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/texture/OpenGLTextureData.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/texture/OpenGLTextureData.kt @@ -22,12 +22,31 @@ class OpenGLTextureData( val uvEnd: Vec2?, override val animationData: Int = -1, ) : TextureRenderData { + private val uvEndArray = uvEnd?.array override val shaderTextureId: Int = (array shl 28) or (index shl 12) or (animationData + 1) - override fun transformUV(end: Vec2): Vec2 { - if (uvEnd == null) { + override fun transformUV(end: Vec2?): Vec2 { + if (end == null) { + return uvEnd ?: VEC2_ONE + } + if (uvEndArray == null) { return end } - return end * uvEnd + return Vec2(end.x * uvEndArray[0], end.y * uvEndArray[1]) + } + + override fun transformUV(end: FloatArray?): FloatArray { + if (end == null) { + return uvEndArray ?: ONE_ARRAY + } + if (uvEndArray == null) { + return end + } + return floatArrayOf(end[0] * uvEndArray[0], end[1] * uvEndArray[1]) + } + + companion object { + private val VEC2_ONE = Vec2(1.0f, 1.0f) + private val ONE_ARRAY = VEC2_ONE.array } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/GenericColorMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/GenericColorMesh.kt index 25671ca06..2f9fb3771 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/GenericColorMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/GenericColorMesh.kt @@ -22,14 +22,10 @@ import glm_.vec3.Vec3 open class GenericColorMesh(renderWindow: RenderWindow, primitiveType: PrimitiveTypes = renderWindow.renderSystem.preferredPrimitiveType) : Mesh(renderWindow, GenericColorMeshStruct, primitiveType) { fun addVertex(position: Vec3, color: RGBColor?) { - data.addAll( - floatArrayOf( - position.x, - position.y, - position.z, - Float.fromBits((color ?: ChatColors.WHITE).rgba) - ) - ) + data.add(position.x) + data.add(position.y) + data.add(position.z) + data.add(Float.fromBits((color ?: ChatColors.WHITE).rgba)) } data class GenericColorMeshStruct( diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/LineMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/LineMesh.kt index c5be0fb27..66049b741 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/LineMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/LineMesh.kt @@ -13,6 +13,7 @@ package de.bixilon.minosoft.gui.rendering.util.mesh +import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.AABB import de.bixilon.minosoft.data.registries.VoxelShape import de.bixilon.minosoft.data.text.RGBColor @@ -59,6 +60,15 @@ open class LineMesh(renderWindow: RenderWindow) : GenericColorMesh(renderWindow) drawAABB(aabb + position, lineWidth, color, margin) } + fun drawLazyAABB(aabb: AABB, color: RGBColor) { + for (direction in Directions.VALUES) { + val positions = direction.getPositions(Vec3(aabb.min), Vec3(aabb.max)) + for ((positionIndex, _) in order) { + addVertex(positions[positionIndex], color) + } + } + } + fun drawAABB(aabb: AABB, lineWidth: Float = RenderConstants.DEFAULT_LINE_WIDTH, color: RGBColor, margin: Float = 0.0f) { val min = aabb.min - margin val max = aabb.max + margin diff --git a/src/main/java/de/bixilon/minosoft/util/collections/floats/DirectArrayFloatList.kt b/src/main/java/de/bixilon/minosoft/util/collections/floats/DirectArrayFloatList.kt index 08804d981..1517b5abb 100644 --- a/src/main/java/de/bixilon/minosoft/util/collections/floats/DirectArrayFloatList.kt +++ b/src/main/java/de/bixilon/minosoft/util/collections/floats/DirectArrayFloatList.kt @@ -47,6 +47,7 @@ class DirectArrayFloatList( } } + @Synchronized override fun ensureSize(needed: Int) { checkFinalized() if (limit - size >= needed) { diff --git a/src/main/resources/assets/minosoft/rendering/shader/particle/particle.gsh b/src/main/resources/assets/minosoft/rendering/shader/particle/particle.gsh index b4dee3639..e4e4be283 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/particle/particle.gsh +++ b/src/main/resources/assets/minosoft/rendering/shader/particle/particle.gsh @@ -14,8 +14,7 @@ #version 330 layout (points) in; -layout (triangle_strip) out; -layout (max_vertices = 4) out; +layout (triangle_strip, max_vertices = 4) out; uniform mat4 uViewProjectionMatrix; uniform vec3 uCameraRight;