Skip to content

Commit

Permalink
Fixed #787: IndigoShader, expose ability to add UniformBlocks
Browse files Browse the repository at this point in the history
  • Loading branch information
davesmith00000 committed Nov 18, 2024
1 parent 4914755 commit 1b7a8e5
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 17 deletions.
24 changes: 14 additions & 10 deletions indigo/indigo/src/main/scala/indigo/IndigoShader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package indigo

import indigo.entry.StandardFrameProcessor
import indigo.gameengine.GameEngine
import indigo.shared.shader.UniformBlock
import indigo.shared.shader.library
import indigo.shared.shader.library.IndigoUV.BlendFragmentEnvReference
import indigo.shared.subsystems.SubSystemsRegister
Expand All @@ -11,18 +12,12 @@ import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._
import scala.concurrent.Future

/** A trait representing a shader that fills the available window.
*
* You can override a number of the details in this trait using launch flags, including:
*
* - width - starting width of the shader
* - height - starting height of the shader
* - channel0 - path to an image
* - channel1 - path to an image
* - channel2 - path to an image
* - channel3 - path to an image
*/
trait IndigoShader extends GameLauncher[IndigoShaderModel, IndigoShaderModel, Unit] {

given [A](using toUBO: ToUniformBlock[A]): Conversion[A, UniformBlock] with
def apply(value: A): UniformBlock = toUBO.toUniformBlock(value)

private val Channel0Name: String = "channel0"
private val Channel1Name: String = "channel1"
private val Channel2Name: String = "channel2"
Expand Down Expand Up @@ -52,6 +47,15 @@ trait IndigoShader extends GameLauncher[IndigoShaderModel, IndigoShaderModel, Un
*/
def channel3: Option[AssetPath]

/** The uniform blocks (data) you want to pass to your shader. Example:
*
* ```scala
* final case class CustomData(color: RGBA, customTime: Seconds) extends FragmentEnvReference derives ToUniformBlock
* def uniformBlocks: Batch[UniformBlock] = Batch(CustomData(RGBA.Magenta, 0.seconds))
* ```
*/
def uniformBlocks: Batch[UniformBlock]

/** The shader you want to render
*/
def shader: ShaderProgram
Expand Down Expand Up @@ -139,7 +143,7 @@ trait IndigoShader extends GameLauncher[IndigoShaderModel, IndigoShaderModel, Un
model.viewport,
ShaderData(
shader.id,
Batch.empty,
uniformBlocks,
model.channel0,
model.channel1,
model.channel2,
Expand Down
3 changes: 3 additions & 0 deletions indigo/indigo/src/main/scala/indigo/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ val ShaderId: shared.shader.ShaderId.type = shared.shader.ShaderId
type ToUniformBlock[A] = shared.shader.ToUniformBlock[A]
val ToUniformBlock: shared.shader.ToUniformBlock.type = shared.shader.ToUniformBlock

type UniformBlock = shared.shader.UniformBlock
val UniformBlock: shared.shader.UniformBlock.type = shared.shader.UniformBlock

val StandardShaders: shared.shader.StandardShaders.type = shared.shader.StandardShaders

type Outcome[T] = shared.Outcome[T]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ object ToUniformBlock:
case given ShaderTypeOf[T] => summonInline[ShaderTypeOf[T]]
case _ =>
error(
"Unsupported type. Only supported types in Indigo shaders are: Int, Long, Float, Double, RGBA, RGB, Point, Size, Vertex, Vector2, Vector3, Vector4, Rectangle, Matrix4, Depth, Radians, Millis, Seconds, Array[Float], js.Array[Float]"
"Unsupported shader uniform type. Supported types From Scala (Int, Long, Float, Double), Indigo [RGBA, RGB, Point, Size, Vertex, Vector2, Vector3, Vector4, Rectangle, Matrix4, Depth, Radians, Millis, Seconds, Array[Float], js.Array[Float]], and UltraViolet [vec2, vec3, vec4, mat4]. However, if you intend to use the same case class for both Indigo and UltraViolet, you should stick to Float + the UltraViolet types."
)
}

Expand All @@ -62,6 +62,22 @@ object ToUniformBlock:

object ShaderTypeOf:

given ShaderTypeOf[ultraviolet.syntax.vec2] with
def toShaderPrimitive(value: ultraviolet.syntax.vec2): ShaderPrimitive =
ShaderPrimitive.vec2(value.x, value.y)

given ShaderTypeOf[ultraviolet.syntax.vec3] with
def toShaderPrimitive(value: ultraviolet.syntax.vec3): ShaderPrimitive =
ShaderPrimitive.vec3(value.x, value.y, value.z)

given ShaderTypeOf[ultraviolet.syntax.vec4] with
def toShaderPrimitive(value: ultraviolet.syntax.vec4): ShaderPrimitive =
ShaderPrimitive.vec4(value.x, value.y, value.z, value.w)

given ShaderTypeOf[ultraviolet.syntax.mat4] with
def toShaderPrimitive(value: ultraviolet.syntax.mat4): ShaderPrimitive =
ShaderPrimitive.mat4(value.mat)

given ShaderTypeOf[Int] with
def toShaderPrimitive(value: Int): ShaderPrimitive =
ShaderPrimitive.float(value)
Expand Down
34 changes: 28 additions & 6 deletions indigo/shader/src/main/scala/com/example/shader/ShaderGame.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import indigo.*
import ultraviolet.syntax.*

import scala.scalajs.js.annotation._

Expand All @@ -12,9 +13,34 @@ object ShaderGame extends IndigoShader:
val channel2: Option[AssetPath] = None
val channel3: Option[AssetPath] = None

val uniformBlocks: Batch[UniformBlock] =
Batch(CustomData.reference)

val shader: ShaderProgram =
// ShowImage.shader
SeascapeShader.shader
ShaderWithData.shader
// ShowImage.shader
// SeascapeShader.shader

final case class CustomData(CUSTOM_COLOR: vec4) extends FragmentEnvReference derives ToUniformBlock
object CustomData:
val reference =
CustomData(vec4(1.0f, 0.0f, 1.0f, 1.0f))

object ShaderWithData:

val shader: UltravioletShader =
UltravioletShader.entityFragment(
ShaderId("shader with data"),
EntityShader.fragment[CustomData](shaderWithData, CustomData.reference)
)

inline def shaderWithData: Shader[CustomData, Unit] =
Shader[CustomData] { env =>
ubo[CustomData]

def fragment(color: vec4): vec4 =
env.CUSTOM_COLOR
}

object ShowImage:

Expand All @@ -24,8 +50,6 @@ object ShowImage:
EntityShader.fragment[FragmentEnv](showImage, FragmentEnv.reference)
)

import ultraviolet.syntax.*

inline def showImage: Shader[FragmentEnv, Unit] =
Shader[FragmentEnv] { env =>
def fragment(color: vec4): vec4 =
Expand Down Expand Up @@ -55,8 +79,6 @@ object VoronoiShader:
EntityShader.fragment[FragmentEnv](voronoi, FragmentEnv.reference)
)

import ultraviolet.syntax.*

// Ported from: https://www.youtube.com/watch?v=l-07BXzNdPw&feature=youtu.be
@SuppressWarnings(Array("scalafix:DisableSyntax.var"))
inline def voronoi: Shader[FragmentEnv, Unit] =
Expand Down

0 comments on commit 1b7a8e5

Please sign in to comment.