Skip to content

Commit

Permalink
[multitexturing] refactored transfer function (no longer optional but…
Browse files Browse the repository at this point in the history
… with default value); added blending
  • Loading branch information
haraldsteinlechner committed Jul 20, 2023
1 parent 6973e42 commit 440b991
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 99 deletions.
Empty file added src/Multitexture.md
Empty file.
1 change: 1 addition & 0 deletions src/PRo3D.Base/Multitexturing.fs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type TextureCombiner =
| Primary = 1
| Secondary = 2
| Multiply = 3
| Blend = 4

type TransferFunctionMode =
| Unknown = 0
Expand Down
5 changes: 5 additions & 0 deletions src/PRo3D.Base/Utilities.fs
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,7 @@ module Shader =
member x.TextureCombiner : TextureCombiner = uniform?TextureCombiner
member x.TransferFunctionMode : TransferFunctionMode = uniform?TransferFunctionMode
member x.TFRange : V2d = uniform?TFRange
member x.TFBlendFactor : float = uniform?TFBlendFactor

let secondaryTexture (v : Effects.Vertex) =
fragment {
Expand All @@ -668,13 +669,17 @@ module Shader =
c
else
v.c
| TransferFunctionMode.Passthrough ->
secondaryTextureSampler.Sample(v.tc)
| _ ->
v.c
match uniform.TextureCombiner with
| TextureCombiner.Secondary ->
color <- secondaryColor
| TextureCombiner.Multiply ->
color <- V4d(v.c.XYZ * secondaryColor.XYZ, 1.0)
| TextureCombiner.Blend ->
color <- V4d(v.c.XYZ * (1.0 - uniform.TFBlendFactor) + secondaryColor.XYZ * uniform.TFBlendFactor, 1.0)
| _ ->
color <- v.c

Expand Down
4 changes: 2 additions & 2 deletions src/PRo3D.Core/AardvarkUIReworks.fs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ module NoSemUi =
]


let numeric (cfg : NumericConfig<'a>) (atts : AttributeMap<'msg>) (value : aval<'a>) (update : 'a -> 'msg) =
let numeric (cfg : NumericConfig<'a>) (inputType : string) (atts : AttributeMap<'msg>) (value : aval<'a>) (update : 'a -> 'msg) =

let value = if value.IsConstant then AVal.custom (fun t -> value.GetValue t) else value

Expand Down Expand Up @@ -83,7 +83,7 @@ module NoSemUi =
input (att [

attribute "value" (value.GetValue() |> pickle)
attribute "type" "text"
attribute "type" inputType
attribute "min" (pickle cfg.min)
attribute "max" (pickle cfg.max)
attribute "step" (pickle cfg.smallStep)
Expand Down
8 changes: 6 additions & 2 deletions src/PRo3D.Core/Surface-Model.fs
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,12 @@ type TransferFunction =
{
tf : ColorMaps.TF
textureCombiner : TextureCombiner
blendFactor : float
}

module TransferFunction =
let empty = { tf = ColorMaps.TF.Passthrough; textureCombiner = TextureCombiner.Primary; blendFactor = 1.0 }


[<ModelType>]
type Surface = {
Expand Down Expand Up @@ -411,7 +415,7 @@ type Surface = {
textureLayers : IndexList<TextureLayer>
primaryTexture : Option<TextureLayer>
secondaryTexture : Option<TextureLayer>
transferFunction : Option<TransferFunction>
transferFunction : TransferFunction
opcxPath : Option<string>

[<NonAdaptiveAttribute>]
Expand Down Expand Up @@ -496,7 +500,7 @@ module Surface =
textureLayers = textureLayers
primaryTexture = selectedTexture
secondaryTexture = None
transferFunction = None
transferFunction = TransferFunction.empty
surfaceType = surfaceType |> enum<SurfaceType>
preferredLoader = preferredLoader |> enum<MeshLoaderType>
colorCorrection = colorCorrection
Expand Down
124 changes: 63 additions & 61 deletions src/PRo3D.Core/Surface/Surface-Properties.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ open PRo3D.Core.Surface

module SurfaceProperties =

[<Literal>]
let ramp = "Ramp"
[<Literal>]
let passthrough = "Passthrough"

type Action =
| SetFillMode of FillMode
| SetCullMode of CullMode
Expand All @@ -37,6 +42,7 @@ module SurfaceProperties =
| SetTFMax of float
| SetColorMappingName of Option<string>
| SetTextureCombiner of TextureCombiner
| SetBlendFactor of float

| SetHomePosition //of Guid //of Option<CameraView>

Expand Down Expand Up @@ -73,41 +79,31 @@ module SurfaceProperties =
| SetSecondaryTexture texture ->
{ model with secondaryTexture = texture } |> Console.print

| SetTransferFunctionMode None ->
{ model with transferFunction = None }
| SetTransferFunctionMode name ->
| SetTransferFunctionMode (Some name) ->
match name with
| Some "Ramp" ->
| _ when name = ramp ->
match model.transferFunction with
| Some { tf = ColorMaps.TF.Ramp(_,_,_); textureCombiner = _ } -> model
| _ -> { model with transferFunction = Some { tf = ColorMaps.TF.Ramp(0.0, 1.0, ColorMaps.colorMaps |> Map.toSeq |> Seq.head |> fst); textureCombiner = TextureCombiner.Multiply } }
| Some "Passthrough" ->
{ model with transferFunction = Some { tf = ColorMaps.TF.Passthrough; textureCombiner = TextureCombiner.Multiply }}
| None -> { model with transferFunction = None }
| Some name ->
| { tf = ColorMaps.TF.Ramp(_,_,_); textureCombiner = _ } -> model
| _ -> { model with transferFunction = { model.transferFunction with tf = ColorMaps.TF.Ramp(0.0, 1.0, ColorMaps.colorMaps |> Map.toSeq |> Seq.head |> fst); } }
| _ when name = passthrough->
{ model with transferFunction = { model.transferFunction with tf = ColorMaps.TF.Passthrough }}
| _ ->
Log.warn "unkonwn tf mode: %s" name
model
| SetTransferFunctionMode None -> model

| SetTFMin min ->
match model.transferFunction with
| None -> model
| Some tf ->
{ model with transferFunction = Some { tf with tf = ColorMaps.TF.trySetMin min tf.tf; } }
{ model with transferFunction = { model.transferFunction with tf = ColorMaps.TF.trySetMin min model.transferFunction.tf; } }
| SetTFMax max ->
match model.transferFunction with
| None -> model
| Some tf ->
{ model with transferFunction = Some { tf with tf = ColorMaps.TF.trySetMax max tf.tf } }
{ model with transferFunction = { model.transferFunction with tf = ColorMaps.TF.trySetMax max model.transferFunction.tf; } }

| SetColorMappingName None -> model
| SetColorMappingName (Some name) ->
match model.transferFunction with
| None -> model
| Some tf ->
{ model with transferFunction = Some { tf with tf = ColorMaps.TF.trySetName name tf.tf } }
{ model with transferFunction = { model.transferFunction with tf = ColorMaps.TF.trySetName name model.transferFunction.tf } }
| SetTextureCombiner c ->
match model.transferFunction with
| None -> model
| Some tf ->
{ model with transferFunction = Some { tf with textureCombiner = c } }
{ model with transferFunction = { model.transferFunction with textureCombiner = c } }
| SetBlendFactor f ->
{ model with transferFunction = { model.transferFunction with blendFactor = f }}


| SetHomePosition -> model
Expand Down Expand Up @@ -172,47 +168,53 @@ module SurfaceProperties =

let tfToName (tf : ColorMaps.TF) =
match tf with
| ColorMaps.TF.Ramp(_,_,_) -> "Ramp"
| ColorMaps.TF.Passthrough -> "Passthrough"
| ColorMaps.TF.Ramp(_,_,_) -> ramp
| ColorMaps.TF.Passthrough -> passthrough


yield Html.row "Transfer Function" [ div [] [UI.dropDown'' (AList.ofList ["Passthrough"; "Ramp"]) (model.transferFunction |> AVal.map (function None -> None | Some tf -> Some (tfToName tf.tf))) SetTransferFunctionMode (fun a -> a)]]
yield Html.row "Transfer Function" [ div [] [UI.dropDown'' (AList.ofList [ramp; passthrough]) (model.transferFunction |> AVal.map (fun tf -> Some (tfToName tf.tf))) SetTransferFunctionMode (fun a -> a)]]
yield Html.row "Secondary Texture:" [UI.dropDown'' model.textureLayers model.secondaryTexture (fun x -> SetSecondaryTexture x) (fun x -> x.label)]

let! tf = model.transferFunction
match tf with
| None -> ()
| Some tf ->
yield Html.row "Texture Combiner" [Html.SemUi.dropDown (AVal.constant tf.textureCombiner) SetTextureCombiner]

match tf.tf with
| ColorMaps.TF.Ramp(min,max,name) ->
yield Html.row "Min" [
yield Aardvark.UI.NoSemUi.numeric { min = 0.0; max = 1.0; smallStep = 0.01; largeStep = 0.1 } AttributeMap.empty (
match tf.tf with
| ColorMaps.TF.Ramp(min, max, name) -> min |> AVal.constant
| _ -> 0.0 |> AVal.constant
) SetTFMin
]
yield Html.row "Max" [
yield Aardvark.UI.NoSemUi.numeric { min = 0.0; max = 1.0; smallStep = 0.01; largeStep = 0.1 } AttributeMap.empty (
match tf.tf with
| ColorMaps.TF.Ramp(min, max, name) -> max |> AVal.constant
| _ -> 0.0 |> AVal.constant
) SetTFMax
]
let toColorMapName (tf : ColorMaps.TF) =
match tf with
| ColorMaps.TF.Ramp(_,_,s) -> Some s
| _ -> None
//let candidates =
// let availableColorMaps = ColorMaps.colorMaps |> List.map (fun (s,_) -> Some s, s) |> Map.ofList
// Map.union (Map.ofList [None, "No color map"]) availableColorMaps
//yield Simple.dropDown [] (toColorMapName tf.tf |> AVal.constant) SetColorMappingName candidates
yield Html.row "Color Map" [
yield UI.dropDown'' (ColorMaps.colorMaps |> Map.toSeq |> Seq.map fst |> AList.ofSeq) (toColorMapName tf.tf |> AVal.constant) (fun x -> SetColorMappingName x) (fun s -> s)
]
| _ -> ()
yield Html.row "Texture Combiner" [Html.SemUi.dropDown (AVal.constant tf.textureCombiner) SetTextureCombiner]

match tf.textureCombiner with
| TextureCombiner.Blend ->
yield
Html.row "Blend Factor" [Aardvark.UI.NoSemUi.numeric { min = 0.0; max = 1.0; smallStep = 0.01; largeStep = 0.1 } "range" AttributeMap.empty (
tf.blendFactor |> AVal.constant
) SetBlendFactor
]
| _ ->
()

match tf.tf with
| ColorMaps.TF.Ramp(min,max,name) ->
yield Html.row "Min" [
yield Aardvark.UI.NoSemUi.numeric { min = 0.0; max = 1.0; smallStep = 0.01; largeStep = 0.1 } "text" AttributeMap.empty (
match tf.tf with
| ColorMaps.TF.Ramp(min, max, name) -> min |> AVal.constant
| _ -> 0.0 |> AVal.constant
) SetTFMin
]
yield Html.row "Max" [
yield Aardvark.UI.NoSemUi.numeric { min = 0.0; max = 1.0; smallStep = 0.01; largeStep = 0.1 } "text" AttributeMap.empty (
match tf.tf with
| ColorMaps.TF.Ramp(min, max, name) -> max |> AVal.constant
| _ -> 0.0 |> AVal.constant
) SetTFMax
]
let toColorMapName (tf : ColorMaps.TF) =
match tf with
| ColorMaps.TF.Ramp(_,_,s) -> Some s
| _ -> None

yield Html.row "Color Map" [
yield UI.dropDown'' (ColorMaps.colorMaps |> Map.toSeq |> Seq.map fst |> AList.ofSeq) (toColorMapName tf.tf |> AVal.constant) (fun x -> SetColorMappingName x) (fun s -> s)
]
| _ -> ()


}
)
Expand Down
2 changes: 1 addition & 1 deletion src/PRo3D.Core/Surface/SurfaceApp.fs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ module SurfaceUtils =
primaryTexture = None

secondaryTexture = None
transferFunction = None
transferFunction = TransferFunction.empty

triangleSize = { Init.triangleSize with value = maxTriangleSize }

Expand Down
53 changes: 21 additions & 32 deletions src/PRo3D.Viewer/Viewer/Viewer-Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -390,50 +390,39 @@ module ViewerUtils =

|> Sg.texture "SecondaryTextureTransferFunction" (
surf.transferFunction |> AVal.map (fun tf ->
match tf with
| None -> NullTexture.Instance
| Some tf ->
match tf.tf with
| ColorMaps.TF.Passthrough -> NullTexture.Instance
| ColorMaps.TF.Ramp(_,_,name) ->
match Map.tryFind name ColorMaps.colorMaps with
| None -> NullTexture.Instance
| Some l ->
try
l.Value :> ITexture
with e ->
Log.warn "SecondaryTextureTransferFunction: %A" e
NullTexture.Instance
match tf.tf with
| ColorMaps.TF.Passthrough -> NullTexture.Instance
| ColorMaps.TF.Ramp(_,_,name) ->
match Map.tryFind name ColorMaps.colorMaps with
| None -> NullTexture.Instance
| Some l ->
try
l.Value :> ITexture
with e ->
Log.warn "SecondaryTextureTransferFunction: %A" e
NullTexture.Instance
)
)
|> Sg.uniform "TextureCombiner" (
surf.transferFunction |> AVal.map (fun tf ->
match tf with
| None -> TextureCombiner.Unknown
| Some tf ->
tf.textureCombiner
)
surf.transferFunction |> AVal.map (fun tf -> tf.textureCombiner)
)
|> Sg.uniform "TransferFunctionMode" (
surf.transferFunction |> AVal.map (fun tf ->
match tf with
| None -> TransferFunctionMode.Unknown
| Some tf ->
match tf.tf with
| ColorMaps.TF.Passthrough -> TransferFunctionMode.Passthrough
| ColorMaps.TF.Ramp(_,_,_) -> TransferFunctionMode.Ramp
match tf.tf with
| ColorMaps.TF.Passthrough -> TransferFunctionMode.Passthrough
| ColorMaps.TF.Ramp(_,_,_) -> TransferFunctionMode.Ramp
)
)
|> Sg.uniform "TFRange" (
surf.transferFunction |> AVal.map (fun tf ->
match tf with
| None -> V2d.OI
| Some tf ->
match tf.tf with
| ColorMaps.TF.Passthrough -> V2d.OI
| ColorMaps.TF.Ramp(min,max,_) -> V2d(min, max)
match tf.tf with
| ColorMaps.TF.Passthrough -> V2d.OI
| ColorMaps.TF.Ramp(min,max,_) -> V2d(min, max)
)
)
|> Sg.uniform "TFBlendFactor" (
surf.transferFunction |> AVal.map (fun tf -> tf.blendFactor)
)


|> Sg.withEvents [
Expand Down
6 changes: 5 additions & 1 deletion src/PRo3D.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "PRo3D.Lite", "PRo3D.Lite\PR
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EC91D5A1-9C4B-45A2-843C-CB687BF9581F}"
ProjectSection(SolutionItems) = preProject
..\docs\Build-Deploy-System.md = ..\docs\Build-Deploy-System.md
Multitexture.md = Multitexture.md
..\paket.dependencies = ..\paket.dependencies
..\docs\spice.md = ..\docs\spice.md
..\docs\Structure.md = ..\docs\Structure.md
EndProjectSection
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Tests", "Tests\Tests.fsproj", "{D71C7F9E-2847-4218-9FE9-31777CD0B470}"
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Tests", "Tests\Tests.fsproj", "{D71C7F9E-2847-4218-9FE9-31777CD0B470}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down

0 comments on commit 440b991

Please sign in to comment.