Тесселятор тайлов теперь знает про haltOnMatch
This commit is contained in:
parent
f0af2d5a8e
commit
4bd1cae5e1
@ -162,6 +162,14 @@ private fun loop() {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for (x in 0 .. 24) {
|
||||
for (y in 0 .. 24) {
|
||||
chunk[x, y] = Starbound.getTileDefinition("sewerpipe")
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
val chunkRenderer = ChunkRenderer(state, chunk)
|
||||
chunkRenderer.tesselateStatic()
|
||||
chunkRenderer.uploadStatic()
|
||||
|
@ -188,8 +188,8 @@ sealed class RenderRule(params: Map<String, Any>) {
|
||||
"EqualsSelf" -> RenderRuleEqualsSelf(params)
|
||||
"Shadows" -> RenderRuleShadows(params)
|
||||
|
||||
// неизвестно что оно делает
|
||||
"Connects" -> AlwaysFailingRenderRule(params)
|
||||
// неизвестно что оно делает, но вероятнее всего, есть ли там что либо в принципе
|
||||
"Connects" -> RenderRuleConnects(params)
|
||||
|
||||
else -> throw IllegalArgumentException("Unknown render rule '$name'")
|
||||
}
|
||||
@ -236,6 +236,15 @@ class RenderRuleShadows(params: Map<String, Any>) : RenderRule(params) {
|
||||
}
|
||||
}
|
||||
|
||||
class RenderRuleConnects(params: Map<String, Any>) : RenderRule(params) {
|
||||
override fun test(getter: IChunk, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
||||
if (inverse)
|
||||
return getter[thisPos + offsetPos] == null
|
||||
|
||||
return getter[thisPos + offsetPos] != null
|
||||
}
|
||||
}
|
||||
|
||||
class AlwaysPassingRenderRule(params: Map<String, Any>) : RenderRule(params) {
|
||||
override fun test(getter: IChunk, thisRef: TileDefinition, thisPos: Vector2i, offsetPos: Vector2i): Boolean {
|
||||
return inverse
|
||||
@ -345,10 +354,19 @@ data class TileRenderMatchPositioned(
|
||||
data class TileRenderMatchPiece(
|
||||
val pieces: List<TileRenderMatchedPiece>,
|
||||
val matchAllPoints: List<TileRenderMatchPositioned>,
|
||||
val subMatches: List<TileRenderMatchPiece>
|
||||
val matchAnyPoints: List<TileRenderMatchPositioned>,
|
||||
val subMatches: List<TileRenderMatchPiece>,
|
||||
val haltOnSubMatch: Boolean,
|
||||
val haltOnMatch: Boolean
|
||||
) {
|
||||
init {
|
||||
if (matchAnyPoints.isNotEmpty() || matchAllPoints.isNotEmpty()) {
|
||||
require(matchAnyPoints.isEmpty() || matchAllPoints.isEmpty()) { "Both matchAllPoints and matchAnyPoints are present, this is not valid." }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает, сработали ли ВСЕ [matchAllPoints]
|
||||
* Возвращает, сработали ли ВСЕ [matchAllPoints] или ЛЮБОЙ ИЗ [matchAnyPoints]
|
||||
*
|
||||
* Если хотя бы один из них вернул false, весь тест возвращает false
|
||||
*
|
||||
@ -361,7 +379,17 @@ data class TileRenderMatchPiece(
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
if (matchAnyPoints.isEmpty()) {
|
||||
return true
|
||||
}
|
||||
|
||||
for (matcher in matchAnyPoints) {
|
||||
if (matcher.test(getter, thisRef, thisPos)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
companion object {
|
||||
@ -386,6 +414,16 @@ data class TileRenderMatchPiece(
|
||||
return@let ImmutableList.copyOf(list)
|
||||
} ?: listOf()
|
||||
|
||||
val matchAnyPoints = input["matchAnyPoints"]?.asJsonArray?.let {
|
||||
val list = ArrayList<TileRenderMatchPositioned>()
|
||||
|
||||
for (thisPiece in it) {
|
||||
list.add(TileRenderMatchPositioned.fromJson(thisPiece.asJsonArray, rulePieces))
|
||||
}
|
||||
|
||||
return@let ImmutableList.copyOf(list)
|
||||
} ?: listOf()
|
||||
|
||||
val subMatches = input["subMatches"]?.asJsonArray?.let {
|
||||
val list = ArrayList<TileRenderMatchPiece>()
|
||||
|
||||
@ -396,7 +434,18 @@ data class TileRenderMatchPiece(
|
||||
return@let ImmutableList.copyOf(list)
|
||||
} ?: listOf()
|
||||
|
||||
return TileRenderMatchPiece(pieces, matchAllPoints, subMatches)
|
||||
val haltOnSubMatch = input["haltOnSubMatch"]?.asBoolean ?: false
|
||||
val haltOnMatch = input["haltOnMatch"]?.asBoolean ?: false
|
||||
|
||||
return TileRenderMatchPiece(
|
||||
pieces = pieces,
|
||||
matchAllPoints = matchAllPoints,
|
||||
matchAnyPoints = matchAnyPoints,
|
||||
subMatches = subMatches,
|
||||
|
||||
haltOnSubMatch = haltOnSubMatch,
|
||||
haltOnMatch = haltOnMatch,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -410,8 +459,12 @@ data class TileRenderMatch(
|
||||
val name = input[0].asString
|
||||
val pieces = ArrayList<TileRenderMatchPiece>()
|
||||
|
||||
for (elem in input[1].asJsonArray) {
|
||||
pieces.add(TileRenderMatchPiece.fromJson(elem.asJsonObject, tilePieces, rulePieces))
|
||||
try {
|
||||
for (elem in input[1].asJsonArray) {
|
||||
pieces.add(TileRenderMatchPiece.fromJson(elem.asJsonObject, tilePieces, rulePieces))
|
||||
}
|
||||
} catch(err: Throwable) {
|
||||
throw IllegalArgumentException("Failed to deserialize render match rule $name", err)
|
||||
}
|
||||
|
||||
return TileRenderMatch(name, ImmutableList.copyOf(pieces))
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.dbotthepony.kstarbound.render
|
||||
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.lwjgl.glfw.GLFW.glfwGetTime
|
||||
import org.lwjgl.opengl.GL46.*
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
@ -12,7 +13,10 @@ import ru.dbotthepony.kstarbound.math.Vector2i
|
||||
import ru.dbotthepony.kstarbound.world.IChunk
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
data class TileLayer(val bakedProgramState: BakedProgramState, val vertexBuilder: VertexBuilder, val zPos: Int)
|
||||
data class TileLayer(
|
||||
val bakedProgramState: BakedProgramState,
|
||||
val vertexBuilder: VertexBuilder,
|
||||
val zPos: Int)
|
||||
|
||||
class TileLayerList {
|
||||
private val layers = HashMap<BakedProgramState, ArrayList<TileLayer>>()
|
||||
@ -63,6 +67,7 @@ class TileRenderers(val state: GLStateTracker) {
|
||||
override fun setup() {
|
||||
super.setup()
|
||||
state.activeTexture = 0
|
||||
// state.depthTest = true
|
||||
program["_texture"] = 0
|
||||
texture.bind()
|
||||
texture.textureMagFilter = GL_NEAREST
|
||||
@ -94,12 +99,19 @@ class TileRenderers(val state: GLStateTracker) {
|
||||
}
|
||||
}
|
||||
|
||||
private enum class TileRenderTesselateResult {
|
||||
NO_MATCH,
|
||||
CONTINUE,
|
||||
HALT
|
||||
}
|
||||
|
||||
class TileRenderer(val state: GLStateTracker, val tile: TileDefinition) {
|
||||
val texture = state.loadNamedTexture(tile.render.texture).also {
|
||||
it.textureMagFilter = GL_NEAREST
|
||||
}
|
||||
|
||||
val bakedProgramState = state.tileRenderers.simpleProgram(texture)
|
||||
// private var notifiedDepth = false
|
||||
|
||||
private fun tesselateAt(piece: TileRenderPiece, getter: IChunk, builder: VertexBuilder, pos: Vector2i, offset: Vector2i = Vector2i.ZERO) {
|
||||
val fx = pos.x.toFloat()
|
||||
@ -121,10 +133,18 @@ class TileRenderer(val state: GLStateTracker, val tile: TileDefinition) {
|
||||
d += offset.y / BASELINE_TEXTURE_SIZE
|
||||
}
|
||||
|
||||
/*
|
||||
if (!notifiedDepth && tile.render.zLevel >= 5900) {
|
||||
LOGGER.warn("Tile {} has out of bounds zLevel of {}", tile.materialName, tile.render.zLevel)
|
||||
notifiedDepth = true
|
||||
}
|
||||
*/
|
||||
|
||||
if (tile.render.variants == 0 || piece.texture != null || piece.variantStride == null) {
|
||||
val (u0, v0) = texture.pixelToUV(piece.texturePosition)
|
||||
val (u1, v1) = texture.pixelToUV(piece.texturePosition + piece.textureSize)
|
||||
|
||||
//builder.quadZ(a, b, c, d, tile.render.zLevel.toFloat() + 200f, VertexTransformers.uv(u0, v1, u1, v0))
|
||||
builder.quadZ(a, b, c, d, Z_LEVEL, VertexTransformers.uv(u0, v1, u1, v0))
|
||||
} else {
|
||||
val variant = (getter.randomDoubleFor(pos) * tile.render.variants).toInt()
|
||||
@ -132,15 +152,16 @@ class TileRenderer(val state: GLStateTracker, val tile: TileDefinition) {
|
||||
val (u0, v0) = texture.pixelToUV(piece.texturePosition + piece.variantStride * variant)
|
||||
val (u1, v1) = texture.pixelToUV(piece.texturePosition + piece.textureSize + piece.variantStride * variant)
|
||||
|
||||
//builder.quadZ(a, b, c, d, tile.render.zLevel.toFloat() + 200f, VertexTransformers.uv(u0, v1, u1, v0))
|
||||
builder.quadZ(a, b, c, d, Z_LEVEL, VertexTransformers.uv(u0, v1, u1, v0))
|
||||
}
|
||||
}
|
||||
|
||||
private fun tesselatePiece(matchPiece: TileRenderMatchPiece, getter: IChunk, layers: TileLayerList, pos: Vector2i, thisBuilder: VertexBuilder) {
|
||||
private fun tesselatePiece(matchPiece: TileRenderMatchPiece, getter: IChunk, layers: TileLayerList, pos: Vector2i, thisBuilder: VertexBuilder): TileRenderTesselateResult {
|
||||
if (matchPiece.test(getter, tile, pos)) {
|
||||
for (renderPiece in matchPiece.pieces) {
|
||||
if (renderPiece.piece.texture != null) {
|
||||
tesselateAt(renderPiece.piece, getter, layers.getLayer(state.tileRenderers.simpleProgram(state.loadNamedTexture(renderPiece.piece.texture)), tile.render.zLevel - 1) {
|
||||
tesselateAt(renderPiece.piece, getter, layers.getLayer(state.tileRenderers.simpleProgram(state.loadNamedTexture(renderPiece.piece.texture)), tile.render.zLevel) {
|
||||
return@getLayer VertexBuilder(GLFlatAttributeList.VERTEX_TEXTURE, VertexType.QUADS)
|
||||
}, pos, renderPiece.offset)
|
||||
} else {
|
||||
@ -149,9 +170,21 @@ class TileRenderer(val state: GLStateTracker, val tile: TileDefinition) {
|
||||
}
|
||||
|
||||
for (subPiece in matchPiece.subMatches) {
|
||||
tesselatePiece(subPiece, getter, layers, pos, thisBuilder)
|
||||
val matched = tesselatePiece(subPiece, getter, layers, pos, thisBuilder)
|
||||
|
||||
if (matched == TileRenderTesselateResult.HALT || matched == TileRenderTesselateResult.CONTINUE && matchPiece.haltOnSubMatch) {
|
||||
return TileRenderTesselateResult.HALT
|
||||
}
|
||||
}
|
||||
|
||||
if (matchPiece.haltOnMatch) {
|
||||
return TileRenderTesselateResult.HALT
|
||||
}
|
||||
|
||||
return TileRenderTesselateResult.CONTINUE
|
||||
}
|
||||
|
||||
return TileRenderTesselateResult.NO_MATCH
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,7 +207,11 @@ class TileRenderer(val state: GLStateTracker, val tile: TileDefinition) {
|
||||
|
||||
for ((_, matcher) in tile.render.renderTemplate.matches) {
|
||||
for (matchPiece in matcher.pieces) {
|
||||
tesselatePiece(matchPiece, getter, layers, pos, builder)
|
||||
val matched = tesselatePiece(matchPiece, getter, layers, pos, builder)
|
||||
|
||||
if (matched == TileRenderTesselateResult.HALT) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,5 +312,6 @@ class TileRenderer(val state: GLStateTracker, val tile: TileDefinition) {
|
||||
companion object {
|
||||
const val BASELINE_TEXTURE_SIZE = 8f
|
||||
const val Z_LEVEL = 1f
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,10 @@ in vec2 _uv_out;
|
||||
out vec4 _color_out;
|
||||
|
||||
void main() {
|
||||
_color_out = texture(_texture, _uv_out);
|
||||
//_color_out = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
vec4 texel = texture(_texture, _uv_out);
|
||||
|
||||
//if (texel.a < 0.5)
|
||||
// discard;
|
||||
|
||||
_color_out = texel;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user