Skip to content

Commit b319ddd

Browse files
committed
Implement projection shader preview.
1 parent 7ecd861 commit b319ddd

File tree

16 files changed

+318
-90
lines changed

16 files changed

+318
-90
lines changed

src/commonMain/kotlin/baaahs/Mapper.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,13 +609,15 @@ class Mapper(
609609
val solidShader = SolidBrainShader()
610610
solidShader.createBuffer(object : Fixture {
611611
override val pixelCount = SparkleMotion.MAX_PIXEL_COUNT
612+
override val pixelLocations: List<Vector3F?>? get() = null
612613

613614
override fun describe(): String = "Mapper surface"
614615
}).apply { this.color = color }
615616
} else {
616617
val pixelShader = PixelBrainShader(PixelBrainShader.Encoding.INDEXED_2)
617618
pixelShader.createBuffer(object : Fixture {
618619
override val pixelCount = SparkleMotion.MAX_PIXEL_COUNT
620+
override val pixelLocations: List<Vector3F?>? get() = null
619621

620622
override fun describe(): String = "Mapper surface"
621623
}).apply {
@@ -804,6 +806,7 @@ class Mapper(
804806
val pixelShader = PixelBrainShader(PixelBrainShader.Encoding.INDEXED_2)
805807
val pixelShaderBuffer = pixelShader.createBuffer(object : Fixture {
806808
override val pixelCount = SparkleMotion.MAX_PIXEL_COUNT
809+
override val pixelLocations: List<Vector3F?>? get() = null
807810

808811
override fun describe(): String = "Mapper surface"
809812
}).apply {

src/commonMain/kotlin/baaahs/fixtures/Fixture.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import baaahs.model.Model
1212
*/
1313
interface Fixture {
1414
val pixelCount: Int
15+
val pixelLocations: List<Vector3F?>?
1516

1617
fun describe(): String
1718
}
@@ -23,7 +24,7 @@ class IdentifiedFixture(
2324
val modelSurface: Model.Surface,
2425
override val pixelCount: Int,
2526
/** Each pixel's location in the global 3d model. */
26-
val pixelLocations: List<Vector3F?>? = emptyList()
27+
override val pixelLocations: List<Vector3F?>? = emptyList()
2728
) : Fixture {
2829
val name: String = modelSurface.name
2930
override fun describe(): String = modelSurface.description
@@ -53,6 +54,7 @@ class AnonymousFixture(
5354
val brainId: BrainId,
5455
override val pixelCount: Int = SparkleMotion.MAX_PIXEL_COUNT
5556
) : Fixture {
57+
override val pixelLocations: List<Vector3F?>? get() = null
5658
override fun describe(): String = "Anonymous fixture at $brainId"
5759
override fun equals(other: Any?): Boolean = other is AnonymousFixture && brainId.equals(other.brainId)
5860
override fun hashCode(): Int = brainId.hashCode()

src/commonMain/kotlin/baaahs/gl/GlContext.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package baaahs.gl
22

33
import baaahs.Logger
4+
import baaahs.gl.glsl.CompilationException
45
import baaahs.gl.glsl.CompiledShader
56
import baaahs.gl.glsl.GlslProgram
67
import baaahs.glsl.Uniform
@@ -46,6 +47,23 @@ abstract class GlContext(
4647
return CompiledShader(this, GL_FRAGMENT_SHADER, source)
4748
}
4849

50+
fun compile(vertexShader: CompiledShader, fragShader: CompiledShader): Program {
51+
return runInContext {
52+
val program = runInContext { check { createProgram() ?: throw IllegalStateException() } }
53+
check { attachShader(program, vertexShader.shaderId) }
54+
check { attachShader(program, fragShader.shaderId) }
55+
check { linkProgram(program) }
56+
if (check { getProgramParameter(program, GL_LINK_STATUS) } != GL_TRUE) {
57+
vertexShader.validate()
58+
fragShader.validate()
59+
60+
val infoLog = check { getProgramInfoLog(program) }
61+
throw CompilationException(infoLog ?: "Huh? Program error?")
62+
}
63+
program
64+
}
65+
}
66+
4967
fun useProgram(glslProgram: GlslProgram) {
5068
if (activeProgram !== glslProgram) {
5169
check { useProgram(glslProgram.id) }

src/commonMain/kotlin/baaahs/gl/glsl/GlslProgram.kt

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,57 +9,24 @@ import baaahs.gl.render.ModelRenderer
99
import baaahs.glsl.Uniform
1010
import baaahs.show.DataSource
1111
import baaahs.show.OutputPortRef
12-
import com.danielgergely.kgl.GL_LINK_STATUS
13-
import com.danielgergely.kgl.GL_TRUE
1412

1513
class GlslProgram(
1614
internal val gl: GlContext,
1715
private val linkedPatch: LinkedPatch,
1816
resolver: Resolver
1917
) {
20-
internal val id = gl.runInContext { gl.check { createProgram() ?: throw IllegalStateException() } }
2118

2219
private val vertexShader =
2320
gl.createVertexShader(
24-
"""
25-
#version ${gl.glslVersion}
26-
27-
precision lowp float;
28-
29-
// xy = vertex position in normalized device coordinates ([-1,+1] range).
30-
in vec2 Vertex;
31-
32-
const vec2 scale = vec2(0.5, 0.5);
33-
34-
void main()
35-
{
36-
vec2 vTexCoords = Vertex * scale + scale; // scale vertex attribute to [0,1] range
37-
gl_Position = vec4(Vertex, 0.0, 1.0);
38-
}
39-
""".trimIndent()
21+
"#version ${gl.glslVersion}\n${GlslProgram.vertexShader}"
4022
)
4123

4224
internal val fragShader =
4325
gl.createFragmentShader(linkedPatch.toFullGlsl(gl.glslVersion))
4426

45-
private val bindings: List<Binding>
27+
val id = gl.compile(vertexShader, fragShader)
4628

47-
init {
48-
gl.runInContext {
49-
gl.check { attachShader(id, vertexShader.shaderId) }
50-
gl.check { attachShader(id, fragShader.shaderId) }
51-
gl.check { linkProgram(id) }
52-
if (gl.check { getProgramParameter(id, GL_LINK_STATUS) } != GL_TRUE) {
53-
vertexShader.validate()
54-
fragShader.validate()
55-
56-
val infoLog = gl.check { getProgramInfoLog(id) }
57-
throw CompilationException(infoLog ?: "Huh? Program error?")
58-
}
59-
}
60-
61-
bindings = gl.runInContext { bind(resolver) }
62-
}
29+
private val bindings = gl.runInContext { bind(resolver) }
6330

6431
val vertexAttribLocation: Int = gl.runInContext {
6532
gl.check { getAttribLocation(id, "Vertex") }
@@ -169,6 +136,21 @@ class GlslProgram(
169136
private val logger = Logger("GlslProgram")
170137

171138
val PixelColor = OutputPortRef("sm_result")
139+
140+
val vertexShader = """
141+
precision lowp float;
142+
143+
// xy = vertex position in normalized device coordinates ([-1,+1] range).
144+
in vec2 Vertex;
145+
146+
const vec2 scale = vec2(0.5, 0.5);
147+
148+
void main()
149+
{
150+
vec2 vTexCoords = Vertex * scale + scale; // scale vertex attribute to [0,1] range
151+
gl_Position = vec4(Vertex, 0.0, 1.0);
152+
}
153+
""".trimIndent()
172154
}
173155
}
174156

src/commonMain/kotlin/baaahs/gl/preview/PreviewShaderBuilder.kt

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ import baaahs.ui.Observable
2323
import kotlinx.coroutines.GlobalScope
2424
import kotlinx.coroutines.launch
2525

26-
class PreviewShaderBuilder(val shader: Shader, private val autoWirer: AutoWirer): Observable() {
26+
class PreviewShaderBuilder(
27+
val shader: Shader,
28+
private val autoWirer: AutoWirer,
29+
private val modelInfo: ModelInfo
30+
) : Observable() {
2731
var state: State =
2832
State.Unbuilt
2933
private set
@@ -56,7 +60,7 @@ class PreviewShaderBuilder(val shader: Shader, private val autoWirer: AutoWirer)
5660
notifyChanged()
5761

5862
GlobalScope.launch {
59-
val showPlayer = object : BaseShowPlayer(autoWirer.plugins, ModelInfo.Empty) {
63+
val showPlayer = object : BaseShowPlayer(autoWirer.plugins, modelInfo) {
6064
override val glContext: GlContext get() = gl
6165

6266
override fun <T : Gadget> registerGadget(id: String, gadget: T, controlledDataSource: DataSource?) {
@@ -82,24 +86,18 @@ class PreviewShaderBuilder(val shader: Shader, private val autoWirer: AutoWirer)
8286
)
8387
}
8488
val shaders: Array<Shader> = when (shader.type) {
85-
ShaderType.Projection -> arrayOf(shader,
86-
Shaders.smpteColorBars
87-
)
88-
ShaderType.Distortion -> arrayOf(screenCoordsProjection, shader,
89-
Shaders.smpteColorBars
90-
)
89+
ShaderType.Projection -> arrayOf(shader, Shaders.pixelUvIdentity)
90+
ShaderType.Distortion -> arrayOf(screenCoordsProjection, shader, Shaders.smpteColorBars)
9191
ShaderType.Paint -> arrayOf(screenCoordsProjection, shader)
92-
ShaderType.Filter -> arrayOf(screenCoordsProjection, shader,
93-
Shaders.smpteColorBars
94-
)
92+
ShaderType.Filter -> arrayOf(screenCoordsProjection, shader, Shaders.smpteColorBars)
93+
}
94+
95+
val defaultPorts = when (shader.type) {
96+
ShaderType.Projection -> emptyMap()
97+
else -> mapOf(ContentType.UvCoordinateStream to MutableConstPort("gl_FragCoord"))
9598
}
9699

97100
try {
98-
val defaultPorts = mapOf(
99-
ContentType.UvCoordinateStream to MutableConstPort(
100-
"gl_FragCoord"
101-
)
102-
)
103101
previewPatch = autoWirer.autoWire(*shaders, defaultPorts = defaultPorts)
104102
.acceptSymbolicChannelLinks()
105103
.takeFirstIfAmbiguous()
@@ -121,7 +119,7 @@ class PreviewShaderBuilder(val shader: Shader, private val autoWirer: AutoWirer)
121119
try {
122120
glslProgram = linkedPatch?.compile(gl, resolver)
123121
state = State.Success
124-
} catch (e: GlslException) {
122+
} catch (e: GlslException) {
125123
glslErrors = e.errors
126124
state = State.Errors
127125
} catch (e: Exception) {

src/commonMain/kotlin/baaahs/gl/render/ModelRenderer.kt

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package baaahs.gl.render
22

33
import baaahs.Logger
44
import baaahs.fixtures.Fixture
5+
import baaahs.geom.Vector3F
56
import baaahs.gl.GlContext
67
import baaahs.gl.render.ModelRenderer.GlConst.GL_RGBA8
78
import baaahs.glsl.LinearSurfacePixelStrategy
@@ -113,11 +114,23 @@ open class ModelRenderer(
113114

114115
private fun putPixelCoords(fixtureRenderPlan: FixtureRenderPlan, newPixelCoords: FloatArray) {
115116
val fixture = fixtureRenderPlan.fixture
116-
val pixelLocations = LinearSurfacePixelStrategy.forFixture(fixture)
117+
val pixelLocations = fixture.pixelLocations
118+
?: LinearSurfacePixelStrategy.forFixture(fixture)
117119

120+
val pixel0Index = fixtureRenderPlan.renderResult.bufferOffset
121+
val defaultPixelLocation = fixtureRenderPlan.modelInfo.center
122+
fillPixelLocations(newPixelCoords, pixel0Index, pixelLocations, defaultPixelLocation)
123+
}
124+
125+
private fun fillPixelLocations(
126+
newPixelCoords: FloatArray,
127+
pixel0Index: Int,
128+
pixelLocations: List<Vector3F?>,
129+
defaultPixelLocation: Vector3F
130+
) {
118131
pixelLocations.forEachIndexed { i, pixelLocation ->
119-
val bufOffset = (fixtureRenderPlan.renderResult.bufferOffset + i) * 3
120-
val (x, y, z) = pixelLocation ?: fixtureRenderPlan.modelInfo.center
132+
val bufOffset = (pixel0Index + i) * 3
133+
val (x, y, z) = pixelLocation ?: defaultPixelLocation
121134
newPixelCoords[bufOffset] = x // x
122135
newPixelCoords[bufOffset + 1] = y // y
123136
newPixelCoords[bufOffset + 2] = z // z
@@ -273,6 +286,8 @@ open class ModelRenderer(
273286

274287
object GlConst {
275288
val GL_RGBA8 = 0x8058
289+
val GL_RG32F = 0x8230
290+
val GL_RGBA32F = 0x8814
276291
}
277292

278293
interface ResultFormat {

src/commonMain/kotlin/baaahs/glsl/Shaders.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ object Shaders {
126126
float theta = atan(abs(normalDelta.z), normalDelta.x); // theta in range [-π,π]
127127
if (theta < 0.0) theta += (2.0f * PI); // theta in range [0,2π)
128128
float u = theta / (2.0f * PI); // u in range [0,1)
129-
float v = (pixelOffset.y + modelInfo.extents.y / 2.0f) / modelInfo.extents.y;
130129
return vec2(u, v);
131130
}
132131
@@ -140,4 +139,9 @@ object Shaders {
140139
""".trimIndent()
141140
)
142141

142+
val pixelUvIdentity = Shader("Pixel U/V Identity", ShaderType.Paint, """
143+
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
144+
fragColor = vec4(fragCoord.x, fragCoord.y, 0., 1.);
145+
}
146+
""".trimIndent())
143147
}

src/commonMain/kotlin/baaahs/glsl/SurfacePixelStrategy.kt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,6 @@ interface SurfacePixelStrategy {
1313
object RandomSurfacePixelStrategy : SurfacePixelStrategy {
1414
override fun forFixture(fixture: Fixture): List<Vector3F?> {
1515
return when {
16-
fixture is IdentifiedFixture && fixture.pixelLocations != null -> {
17-
fixture.pixelLocations
18-
}
19-
2016
fixture is IdentifiedFixture -> {
2117
// Randomly pick locations within the surface.
2218
val surfaceVertices = fixture.modelSurface.allVertices().toList()
@@ -48,11 +44,6 @@ object LinearSurfacePixelStrategy : SurfacePixelStrategy {
4844
val pixelCount = fixture.pixelCount
4945

5046
return when {
51-
fixture is IdentifiedFixture && fixture.pixelLocations != null -> {
52-
logger.debug { "Surface ${fixture.name} has mapped pixels."}
53-
fixture.pixelLocations
54-
}
55-
5647
fixture is IdentifiedFixture -> {
5748
logger.debug { "Surface ${fixture.name} doesn't have mapped pixels."}
5849
// Generate pixel locations along a line from one vertex to the surface's center.

src/commonMain/kotlin/baaahs/show/mutable/EditingShader.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ package baaahs.show.mutable
22

33
import baaahs.gl.patch.AutoWirer
44
import baaahs.gl.preview.PreviewShaderBuilder
5+
import baaahs.model.ModelInfo
56
import baaahs.randomId
67
import baaahs.show.Shader
78
import baaahs.ui.Observable
89
import baaahs.ui.addObserver
910

1011
class EditingShader(
1112
val mutableShaderInstance: MutableShaderInstance,
12-
private val autoWirer: AutoWirer
13+
private val autoWirer: AutoWirer,
14+
private val modelInfo: ModelInfo
1315
): Observable() {
1416
val id = randomId("EditingShader")
1517
var state = State.Changed
@@ -18,7 +20,7 @@ class EditingShader(
1820
val title: String get() = mutableShader.title
1921

2022
var previewShaderBuilder: PreviewShaderBuilder =
21-
PreviewShaderBuilder(build(), autoWirer)
23+
PreviewShaderBuilder(build(), autoWirer, modelInfo)
2224
private set
2325

2426
val gadgets get() = previewShaderBuilder.gadgets
@@ -39,7 +41,7 @@ class EditingShader(
3941
}
4042

4143
private fun startBuilding() {
42-
val newPreviewShaderBuilder = PreviewShaderBuilder(build(), autoWirer)
44+
val newPreviewShaderBuilder = PreviewShaderBuilder(build(), autoWirer, modelInfo)
4345
newPreviewShaderBuilder.addObserver {
4446
val newState = when (it.state) {
4547
PreviewShaderBuilder.State.Success -> State.Success

src/commonTest/kotlin/baaahs/shaders/util.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import baaahs.BrainShader
44
import baaahs.Color
55
import baaahs.Pixels
66
import baaahs.fixtures.Fixture
7+
import baaahs.geom.Vector3F
78
import baaahs.io.ByteArrayReader
89
import baaahs.io.ByteArrayWriter
910
import kotlin.test.expect
@@ -47,6 +48,7 @@ internal fun <T : BrainShader.Buffer> render(srcBrainShaderAndBuffer: Pair<Brain
4748
render(srcBrainShaderAndBuffer.second, fixture)
4849

4950
class FakeFixture(override val pixelCount: Int) : Fixture {
51+
override val pixelLocations: List<Vector3F?>? get() = null
5052
override fun describe(): String = "fake"
5153
}
5254

0 commit comments

Comments
 (0)