Gouraud Shading in JavaFX

147 views Asked by At

Each face has 3 colors (one for each vertex). I want to use Gouraud shading to blend these colors. So far, I have taken some inspiration from the FXyz library.

My current approach uses the setTextureModeVertices3D from the FXyz library. But this uses density maps, which does not work in my case because the colors don't come from a mathematical formula. My initial idea was to implement it as follows:

  1. Calculate the color for each vertex in the mesh.
  2. Extract a list of all the unique colors
  3. Make a palette of the unique colors
        val palette = object : ColorPalette {
            override fun getNumColors() = colors.size
            override fun getColor(i: Int) = colors.getOrNull(i)?: Color.BLACK
        }
  1. Make a map with as key the point value (x,y,z) and with as value the index of the color
  2. Make a density function that returns the color index from the aforementioned map.
        { point3F ->
            val key = Triple(point3F.x.toInt(), point3F.y.toInt(), point3F.z.toInt())
            pointColorIndexMap[key]!!
        }

I have a feeling my only option is to create one large image where I put in all shaded triangles, and then references those. But I am unsure what the best technique would be here. Any help is appreciated!

Edit:

This is the code I currently use (this is written in Kotlin):

override fun updateMesh() {
    val definition = model.modelDefinition

    val (colors1, colors2, colors3) = definition.calculateFaceColors()
    val uniqueColorHSBValues = (colors1 + colors2 + colors3).toSet().toList()
    val uniqueColors = uniqueColorHSBValues.map { ModelUtil.hsbToColor(it, null) }

    val palette = object : ColorPalette {
        override fun getNumColors() = uniqueColors.size
        override fun getColor(i: Int) = uniqueColors.getOrNull(i)?: Color.BLACK
    }

    val pointColorIndexMap = HashMap<Triple<Int, Int, Int>, Int>()
    for (face in 0 until definition.getFaceCount()) {
        val type = definition.getFaceTypes()?.get(face)?.toInt()?.let { it and 3}?:0
        val (p1, p2, p3) = definition.getPoints(face)
        if (type == RENDER_SHADED_TRIANGLE) {
            pointColorIndexMap[p1] = uniqueColorHSBValues.indexOf(colors1[face])
            pointColorIndexMap[p2] = uniqueColorHSBValues.indexOf(colors2[face])
            pointColorIndexMap[p3] = uniqueColorHSBValues.indexOf(colors3[face])
        } else if (type == RENDER_FLAT_TRIANGLE) {
            pointColorIndexMap[p1] = uniqueColorHSBValues.indexOf(colors1[face])
            pointColorIndexMap[p2] = uniqueColorHSBValues.indexOf(colors1[face])
            pointColorIndexMap[p3] = uniqueColorHSBValues.indexOf(colors1[face])
        }
    }

    setTextureModeVertices3D(palette) { point3F ->
        val key = Triple(point3F.x.toInt(), point3F.y.toInt(), point3F.z.toInt())
        pointColorIndexMap[key]!!
    }

    val meshHelper = MeshHelper(atlas)
    updateMesh(meshHelper)
}
  • This is how my current implementation of the shading looks like. How my implementation currently is with shading
  • This is how my current implementation looks like without the shading. How my implementation currently is without shading
  • This is how I want my implementation of the shading to roughly look like How I want my implementation with shading to look like roughly
  • This is how my palette looks like (9x10 pixels) (enter image description here
0

There are 0 answers