more shadows tests

This commit is contained in:
DBotThePony 2022-09-14 21:35:23 +07:00
parent 1254fb276c
commit 86a8c4a130
Signed by: DBot
GPG Key ID: DCC23B5715498507
11 changed files with 252 additions and 73 deletions

View File

@ -37,9 +37,9 @@ fun main() {
Starbound.addPakPath(File("J:\\Steam\\steamapps\\common\\Starbound\\assets\\packed.pak"))
//Starbound.addPakPath(File("packed.pak"))
/*Starbound.initializeGame { finished, replaceStatus, status ->
Starbound.initializeGame { finished, replaceStatus, status ->
client.putDebugLog(status, replaceStatus)
}*/
}
client.onTermination {
Starbound.terminateLoading = true
@ -172,8 +172,8 @@ fun main() {
//ent.position += Vector2d(y = 14.0, x = -10.0)
ent.position = Vector2d(600.0 + 16.0, 721.0 + 48.0)
//client.camera.pos.x = 578f
//client.camera.pos.y = 695f
client.camera.pos.x = 578f
client.camera.pos.y = 695f
client.onDrawGUI {
client.gl.font.render("${ent.position}", y = 100f, scale = 0.25f)
@ -186,7 +186,7 @@ fun main() {
//client.camera.pos.y = ent.pos.y.toFloat()
}
val lightRenderer = LightRenderer(client.gl)
/*val lightRenderer = LightRenderer(client.gl)
lightRenderer.resizeFramebuffer(client.viewportWidth, client.viewportHeight)
client.onViewportChanged(lightRenderer::resizeFramebuffer)
@ -223,7 +223,7 @@ fun main() {
(client.screenToWorld(client.mouseCoordinatesF) + Vector2f(0.1f)) to Color.GREEN,
(client.screenToWorld(client.mouseCoordinatesF) + Vector2f(-0.1f)) to Color.BLUE,
)) {
lightRenderer.renderHardLight(lightPosition, color, radius = 10f)
lightRenderer.renderSoftLight(lightPosition, color, radius = 40f)
}
for ((lightPosition, color) in listOf(
@ -231,11 +231,11 @@ fun main() {
(client.screenToWorld(client.mouseCoordinatesF) + Vector2f(10.1f)) to Color.GREEN,
(client.screenToWorld(client.mouseCoordinatesF) + Vector2f(9.9f)) to Color.BLUE,
)) {
lightRenderer.renderSoftLight(lightPosition, color, radius = 10f)
//lightRenderer.renderSoftLight(lightPosition, color, radius = 10f)
}
lightRenderer.renderOutputAdditive()
}
}*/
client.gl.box2dRenderer.drawShapes = false
client.gl.box2dRenderer.drawPairs = false

View File

@ -1,17 +1,28 @@
package ru.dbotthepony.kstarbound.client
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import org.lwjgl.opengl.GL11.GL_LINES
import org.lwjgl.opengl.GL11.GL_TRIANGLES
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
import ru.dbotthepony.kstarbound.client.gl.program.GLHardLightGeometryProgram
import ru.dbotthepony.kstarbound.client.gl.program.GLSoftLightGeometryProgram
import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType
import ru.dbotthepony.kstarbound.client.gl.vertex.StatefulVertexBuilder
import ru.dbotthepony.kstarbound.client.gl.vertex.quad
import ru.dbotthepony.kstarbound.client.gl.vertex.shadowQuad
import ru.dbotthepony.kstarbound.client.render.ConfiguredStaticMesh
import ru.dbotthepony.kstarbound.client.render.EntityRenderer
import ru.dbotthepony.kstarbound.client.render.ILayeredRenderer
import ru.dbotthepony.kstarbound.client.render.LightRenderer
import ru.dbotthepony.kstarbound.client.render.TileLayerList
import ru.dbotthepony.kstarbound.defs.liquid.LiquidDefinition
import ru.dbotthepony.kstarbound.world.*
import ru.dbotthepony.kstarbound.world.entities.Entity
import ru.dbotthepony.kvector.matrix.Matrix4fStack
import ru.dbotthepony.kvector.matrix.nfloat.Matrix4f
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
import ru.dbotthepony.kvector.vector.nfloat.Vector2f
import ru.dbotthepony.kvector.vector.nfloat.Vector3f
import java.io.Closeable
import java.util.IdentityHashMap
import java.util.LinkedList
@ -38,16 +49,10 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
for (mesh in bakedMeshes) {
mesh.first.close()
}
bakedMeshes.clear()
} else {
for (mesh in bakedMeshes) {
unloadableBakedMeshes.add(mesh.first)
}
bakedMeshes.clear()
}
bakedMeshes.clear()
layers.clear()
for ((pos, tile) in view.posToTile) {
@ -141,8 +146,6 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
val debugCollisions get() = world.client.settings.debugCollisions
val posVector2d = Vector2d(x = pos.x * CHUNK_SIZEd, y = pos.y * CHUNK_SIZEd)
private val unloadableBakedMeshes = ArrayList<ConfiguredStaticMesh>()
private val foregroundRenderer = TileLayerRenderer(foreground::changeset, isBackground = false)
private val backgroundRenderer = TileLayerRenderer(background::changeset, isBackground = true)
@ -160,28 +163,14 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
* Вызывается перед tesselateStatic()
*/
fun loadRenderers() {
unloadUnused()
foregroundRenderer.loadRenderers(getForegroundView())
backgroundRenderer.loadRenderers(getBackgroundView())
}
private fun unloadUnused() {
if (unloadableBakedMeshes.size != 0) {
for (baked in unloadableBakedMeshes) {
baked.close()
}
unloadableBakedMeshes.clear()
}
}
/**
* Отрисовывает всю геометрию напрямую
*/
fun render(stack: Matrix4fStack) {
unloadUnused()
backgroundRenderer.render(stack)
foregroundRenderer.render(stack)
}
@ -190,8 +179,6 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
* Отрисовывает всю геометрию напрямую, с проверкой, изменился ли чанк
*/
fun bakeAndRender(stack: Matrix4fStack) {
unloadUnused()
backgroundRenderer.bakeAndRender(stack, this::getBackgroundView)
foregroundRenderer.bakeAndRender(stack, this::getForegroundView)
}
@ -205,9 +192,6 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
*
*/
fun bake() {
if (state.isSameThread())
unloadUnused()
backgroundRenderer.autoBake(this::getBackgroundView)
foregroundRenderer.autoBake(this::getForegroundView)
@ -219,12 +203,83 @@ class ClientChunk(world: ClientWorld, pos: ChunkPos) : Chunk<ClientWorld, Client
* Загружает в видеопамять всю геометрию напрямую, если есть что загружать
*/
fun upload() {
unloadUnused()
backgroundRenderer.autoUpload()
foregroundRenderer.autoUpload()
}
private val hardShadowGeometry = StatefulVertexBuilder(state, LightRenderer.SHADOW_FORMAT, GeometryType.QUADS_AS_LINES)
private var hardShadowGeometryRev = -1
private val softShadowGeometry = StatefulVertexBuilder(state, LightRenderer.SHADOW_FORMAT_SOFT, GeometryType.QUADS_ALTERNATIVE)
private var softShadowGeometryRev = -1
val shadowGeometry: LightRenderer.ShadowGeometryRenderer get() {
return object : LightRenderer.ShadowGeometryRenderer {
override fun renderHardGeometry(
renderer: LightRenderer,
lightPosition: Vector2f,
stack: Matrix4fStack,
program: GLHardLightGeometryProgram
) {
if (hardShadowGeometryRev == tileChangeset) {
program.localToWorldTransform.set(Matrix4f.IDENTITY.translateWithMultiplication(Vector3f(x = pos.x * CHUNK_SIZEf, y = pos.y * CHUNK_SIZEf)))
hardShadowGeometry.draw(GL_LINES)
return
}
hardShadowGeometryRev = tileChangeset
val builder = hardShadowGeometry
builder.begin()
for (x in 0 until CHUNK_SIZE) {
for (y in 0 until CHUNK_SIZE) {
if (foreground[x, y].material != null) {
builder.quad(x.toFloat(), y.toFloat(), x + 1f, y + 1f)
}
}
}
builder.upload()
program.localToWorldTransform.set(Matrix4f.IDENTITY.translateWithMultiplication(Vector3f(x = pos.x * CHUNK_SIZEf, y = pos.y * CHUNK_SIZEf)))
builder.draw(GL_LINES)
}
override fun renderSoftGeometry(
renderer: LightRenderer,
lightPosition: Vector2f,
stack: Matrix4fStack,
program: GLSoftLightGeometryProgram
) {
if (softShadowGeometryRev == tileChangeset) {
program.localToWorldTransform.set(Matrix4f.IDENTITY.translateWithMultiplication(Vector3f(x = pos.x * CHUNK_SIZEf, y = pos.y * CHUNK_SIZEf)))
softShadowGeometry.draw(GL_TRIANGLES)
return
}
softShadowGeometryRev = tileChangeset
val builder = softShadowGeometry
builder.begin()
for (x in 0 until CHUNK_SIZE) {
for (y in 0 until CHUNK_SIZE) {
if (foreground[x, y].material != null) {
builder.shadowQuad(x.toFloat(), y.toFloat(), x + 1f, y + 1f)
}
}
}
builder.upload()
program.localToWorldTransform.set(Matrix4f.IDENTITY.translateWithMultiplication(Vector3f(x = pos.x * CHUNK_SIZEf, y = pos.y * CHUNK_SIZEf)))
builder.draw(GL_LINES)
}
}
}
/**
* Хранит состояние отрисовки этого чанка
*

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.kstarbound.client
import org.lwjgl.opengl.GL46.*
import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITf
import ru.dbotthepony.kstarbound.client.gl.BlendFunc
import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers
import ru.dbotthepony.kstarbound.client.gl.vertex.quadZ
import ru.dbotthepony.kstarbound.client.render.ILayeredRenderer
@ -12,6 +13,8 @@ import ru.dbotthepony.kstarbound.util.DoubleEdgeProgression
import ru.dbotthepony.kstarbound.world.*
import ru.dbotthepony.kstarbound.world.entities.Entity
import ru.dbotthepony.kvector.util2d.AABB
import ru.dbotthepony.kvector.vector.Color
import ru.dbotthepony.kvector.vector.nfloat.Vector2f
class ClientWorld(
val client: StarboundClient,
@ -101,13 +104,33 @@ class ClientWorld(
val determineRenderers = ArrayList<ILayeredRenderer>()
client.lightRenderer.begin()
for (chunk in collectPositionAware(size.encasingChunkPosAABB())) {
determineRenderers.add(chunk.second.OneShotRenderer(chunk.first))
chunk.second.bake()
client.lightRenderer.addShadowGeometry(chunk.second.shadowGeometry)
}
renderLayeredList(client.gl.matrixStack, determineRenderers)
for ((lightPosition, color) in listOf(
(client.screenToWorld(client.mouseCoordinatesF)) to Color.RED,
(client.screenToWorld(client.mouseCoordinatesF) + Vector2f(0.1f)) to Color.GREEN,
(client.screenToWorld(client.mouseCoordinatesF) + Vector2f(-0.1f)) to Color.BLUE,
)) {
client.lightRenderer.renderSoftLight(lightPosition, color, radius = 100f)
}
val old = client.gl.blendFunc
client.gl.blendFunc = BlendFunc.MULTIPLY_BY_SRC
client.gl.activeTexture = 0
client.gl.texture2D = client.lightRenderer.outputTexture
client.gl.programs.textureQuad.run()
client.gl.blendFunc = old
physics.debugDraw()
/*for (renderer in determineRenderers) {

View File

@ -14,6 +14,7 @@ import ru.dbotthepony.kstarbound.client.gl.BlendFunc
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
import ru.dbotthepony.kstarbound.client.input.UserInput
import ru.dbotthepony.kstarbound.client.render.Camera
import ru.dbotthepony.kstarbound.client.render.LightRenderer
import ru.dbotthepony.kstarbound.client.render.TextAlignY
import ru.dbotthepony.kstarbound.util.formatBytesShort
import ru.dbotthepony.kvector.matrix.nfloat.Matrix4f
@ -171,6 +172,8 @@ class StarboundClient : AutoCloseable {
viewportMatrixWorld = updateViewportMatrixWorld()
glViewport(0, 0, w, h)
lightRenderer.resizeFramebuffer(viewportWidth, viewportHeight)
for (callback in onViewportChanged) {
callback.invoke(w, h)
}
@ -205,6 +208,11 @@ class StarboundClient : AutoCloseable {
}
val gl = GLStateTracker()
val lightRenderer = LightRenderer(gl)
init {
lightRenderer.resizeFramebuffer(viewportWidth, viewportHeight)
}
var world: ClientWorld? = ClientWorld(this, 0L, 0)

View File

@ -27,7 +27,10 @@ import java.lang.ref.Cleaner
import java.util.concurrent.ThreadFactory
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KMutableProperty0
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty0
private class GLStateSwitchTracker(private val enum: Int, private var value: Boolean = false) {
operator fun getValue(glStateTracker: GLStateTracker, property: KProperty<*>): Boolean {
@ -51,13 +54,13 @@ private class GLStateSwitchTracker(private val enum: Int, private var value: Boo
}
}
private class GLStateGenericTracker<T>(private var value: T, private val callback: (T) -> Unit) {
operator fun getValue(glStateTracker: GLStateTracker, property: KProperty<*>): T {
private class GLStateGenericTracker<T>(private var value: T, private val callback: (T) -> Unit) : ReadWriteProperty<GLStateTracker, T> {
override fun getValue(thisRef: GLStateTracker, property: KProperty<*>): T {
return value
}
operator fun setValue(glStateTracker: GLStateTracker, property: KProperty<*>, value: T) {
glStateTracker.ensureSameThread()
override fun setValue(thisRef: GLStateTracker, property: KProperty<*>, value: T) {
thisRef.ensureSameThread()
if (value == this.value)
return
@ -68,6 +71,35 @@ private class GLStateGenericTracker<T>(private var value: T, private val callbac
}
}
private class TexturesTracker(maxValue: Int) : ReadWriteProperty<GLStateTracker, GLTexture2D?> {
private val values = arrayOfNulls<GLTexture2D>(maxValue)
override fun getValue(thisRef: GLStateTracker, property: KProperty<*>): GLTexture2D? {
return values[thisRef.activeTexture]
}
override fun setValue(thisRef: GLStateTracker, property: KProperty<*>, value: GLTexture2D?) {
thisRef.ensureSameThread()
require(value == null || thisRef === value.state) { "$value does not belong to $thisRef" }
if (values[thisRef.activeTexture] === value) {
return
}
values[thisRef.activeTexture] = value
if (value == null) {
glBindTexture(GL_TEXTURE_2D, 0)
checkForGLError()
return
}
glBindTexture(GL_TEXTURE_2D, value.pointer)
checkForGLError()
}
}
@Suppress("unused")
data class BlendFunc(
val sourceColor: Func,
@ -130,6 +162,13 @@ data class BlendFunc(
Func.ZERO,
Func.ONE
)
val MULTIPLY_BY_SRC = BlendFunc(
Func.ZERO,
Func.SRC_COLOR,
Func.ONE,
Func.ZERO
)
}
}
@ -318,17 +357,6 @@ class GLStateTracker {
var program: GLShaderProgram? = null
private set
var texture2D: GLTexture2D? = null
set(value) {
ensureSameThread()
if (field === value) return
isMe(value?.state)
field = value
if (value == null) return
glBindTexture(GL_TEXTURE_2D, value.pointer)
checkForGLError()
}
var activeTexture = 0
set(value) {
ensureSameThread()
@ -340,6 +368,8 @@ class GLStateTracker {
checkForGLError()
}
var texture2D: GLTexture2D? by TexturesTracker(80)
var clearColor by GLStateGenericTracker<IStruct4f>(Color.WHITE) {
val (r, g, b, a) = it
glClearColor(r, g, b, a)

View File

@ -85,6 +85,7 @@ class GLHardLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(stat
}
val transform = this["transform"]!!
val localToWorldTransform = this["localToWorldTransform"]!!
val lightPosition = this["lightPosition"]!!
val builder by lazy {
@ -99,6 +100,7 @@ class GLSoftLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(stat
val transform = this["transform"]!!
val lightPenetration = this["lightPenetration"]!!
val localToWorldTransform = this["localToWorldTransform"]!!
/**
* Vector3f(x, y, size)

View File

@ -15,17 +15,17 @@ import java.nio.ByteBuffer
*
* Полезен в случаях, когда размер данных для загрузки заранее не известен.
*/
class HeapVertexBuilder(
open class HeapVertexBuilder<T : HeapVertexBuilder<T>>(
attributes: GLAttributeList,
type: GeometryType,
) : AbstractVertexBuilder<HeapVertexBuilder>(attributes, type) {
override val vertexMemory = FastByteArrayOutputStream()
override val elementMemory = FastByteArrayOutputStream()
) : AbstractVertexBuilder<T>(attributes, type) {
final override val vertexMemory = FastByteArrayOutputStream()
final override val elementMemory = FastByteArrayOutputStream()
override var elementIndexType: Int = GL_UNSIGNED_SHORT
final override var elementIndexType: Int = GL_UNSIGNED_SHORT
private set
override fun ensureIndexCapacity() {
final override fun ensureIndexCapacity() {
if (elementIndexType == GL_UNSIGNED_SHORT && elementMemory.length / 2 + type.indices.size >= 30000) {
val backing = elementMemory.array
val copy = FastByteArrayInputStream(ByteArray(elementMemory.length) { backing[it] })
@ -40,12 +40,12 @@ class HeapVertexBuilder(
}
}
override fun resetMemory() {
final override fun resetMemory() {
vertexMemory.reset()
elementMemory.reset()
}
override fun doUpload(vbo: VertexBufferObject, ebo: VertexBufferObject, drawType: Int) {
final override fun doUpload(vbo: VertexBufferObject, ebo: VertexBufferObject, drawType: Int) {
val vboMemory = ByteBuffer.allocateDirect(vertexMemory.length)
vboMemory.put(vertexMemory.array, 0, vertexMemory.length)

View File

@ -0,0 +1,47 @@
package ru.dbotthepony.kstarbound.client.gl.vertex
import org.lwjgl.opengl.GL46
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
import ru.dbotthepony.kstarbound.client.gl.checkForGLError
import java.io.Closeable
class StatefulVertexBuilder(
val state: GLStateTracker,
attributes: GLAttributeList,
type: GeometryType,
) : HeapVertexBuilder<StatefulVertexBuilder>(attributes, type), Closeable {
private val vao = state.newVAO()
private val vbo = state.newVBO()
private val ebo = state.newEBO()
init {
vao.bind()
vbo.bind()
ebo.bind()
attributes.apply(vao, true)
vao.unbind()
vbo.unbind()
ebo.unbind()
}
fun upload(drawType: Int = GL46.GL_STATIC_DRAW) {
upload(vbo, ebo, drawType)
}
fun bind() = vao.bind()
fun unbind() = vao.unbind()
fun draw(primitives: Int = GL46.GL_TRIANGLES) {
bind()
GL46.glDrawElements(primitives, indexCount, elementIndexType, 0L)
checkForGLError()
}
override fun close() {
vao.close()
vbo.close()
ebo.close()
}
}

View File

@ -26,8 +26,8 @@ import ru.dbotthepony.kvector.vector.nfloat.Vector3f
// https://slembcke.github.io/SuperFastSoftShadows
class LightRenderer(val state: GLStateTracker) {
interface ShadowGeometryRenderer {
fun renderHardGeometry(lightPosition: Vector2f, stack: Matrix4fStack, program: GLHardLightGeometryProgram)
fun renderSoftGeometry(lightPosition: Vector2f, stack: Matrix4fStack, program: GLSoftLightGeometryProgram)
fun renderHardGeometry(renderer: LightRenderer, lightPosition: Vector2f, stack: Matrix4fStack, program: GLHardLightGeometryProgram)
fun renderSoftGeometry(renderer: LightRenderer, lightPosition: Vector2f, stack: Matrix4fStack, program: GLSoftLightGeometryProgram)
}
private val geometry = ArrayList<ShadowGeometryRenderer>()
@ -41,6 +41,10 @@ class LightRenderer(val state: GLStateTracker) {
return this.geometry.remove(geometry)
}
fun clearShadowGeometry() {
geometry.clear()
}
/**
* Сюда происходит рендер маски света и самого света
*/
@ -49,7 +53,7 @@ class LightRenderer(val state: GLStateTracker) {
/**
* Сюда накапливается отрисованный свет
*/
private val framebufferAccumulator = GLFrameBuffer(state)
val framebufferAccumulator = GLFrameBuffer(state)
val outputTexture: GLTexture2D? get() = framebufferAccumulator.texture
@ -58,7 +62,7 @@ class LightRenderer(val state: GLStateTracker) {
framebufferAccumulator.reattachTexture(width, height, GL_RGBA)
}
fun begin() {
fun begin(clearGeometry: Boolean = true) {
state.ensureSameThread()
if (!framebufferRender.isComplete || !framebufferAccumulator.isComplete) {
@ -77,6 +81,10 @@ class LightRenderer(val state: GLStateTracker) {
state.clearColor = old
framebufferAccumulator.unbind()
if (clearGeometry) {
geometry.clear()
}
}
/**
@ -161,7 +169,7 @@ class LightRenderer(val state: GLStateTracker) {
state.blendFunc = BlendFunc.ONLY_ALPHA
for (renderer in geometry) {
renderer.renderHardGeometry(position, stack, state.programs.hardLightGeometry)
renderer.renderHardGeometry(this, position, stack, state.programs.hardLightGeometry)
}
state.programs.light.use()
@ -189,7 +197,7 @@ class LightRenderer(val state: GLStateTracker) {
position: Vector2f,
color: Color = Color.WHITE,
radius: Float = 10f,
innerRadius: Float = 1f,
innerRadius: Float = radius / 3f,
stack: Matrix4fStack = state.matrixStack
) {
state.ensureSameThread()
@ -220,7 +228,7 @@ class LightRenderer(val state: GLStateTracker) {
state.blendFunc = BlendFunc.ONLY_BLEND_ALPHA
for (renderer in geometry) {
renderer.renderSoftGeometry(position, stack, state.programs.softLightGeometry)
renderer.renderSoftGeometry(this, position, stack, state.programs.softLightGeometry)
}
state.programs.light.use()
@ -248,6 +256,10 @@ class LightRenderer(val state: GLStateTracker) {
StreamVertexBuilder(state, SHADOW_FORMAT, GeometryType.QUADS_AS_LINES, 256)
}
val hugeBuilder by lazy {
StreamVertexBuilder(state, SHADOW_FORMAT, GeometryType.QUADS_AS_LINES, 16384)
}
val lineBuilder by lazy {
StreamVertexBuilder(state, SHADOW_FORMAT, GeometryType.LINES, 256)
}

View File

@ -4,10 +4,11 @@
layout (location = 0) in vec2 vertexPos;
uniform mat4 transform;
uniform mat4 localToWorldTransform;
out vec2 originalPos;
void main() {
gl_Position = transform * vec4(vertexPos, 0.0, 1.0);
originalPos = vertexPos;
gl_Position = transform * localToWorldTransform * vec4(vertexPos, 0.0, 1.0);
originalPos = (localToWorldTransform * vec4(vertexPos, 0.0, 1.0)).xy;
}

View File

@ -9,6 +9,7 @@ layout (location = 0) in vec4 packedVertexPos;
layout (location = 1) in vec2 edgeType;
uniform mat4 transform;
uniform mat4 localToWorldTransform;
uniform vec3 lightPositionAndSize;
uniform float lightPenetration;
@ -28,8 +29,8 @@ void main() {
float lightSize = lightPositionAndSize.z;
// Unpack the vertex shader input.
vec2 endpoint_a = packedVertexPos.zw;
vec2 endpoint_b = packedVertexPos.xy;
vec2 endpoint_a = (localToWorldTransform * vec4(packedVertexPos.zw, 0.0, 1.0)).xy;
vec2 endpoint_b = (localToWorldTransform * vec4(packedVertexPos.xy, 0.0, 1.0)).xy;
vec2 endpoint = mix(endpoint_a, endpoint_b, edgeType.x);
// Deltas from the segment to the light center.