问题
I'm working in JavaFX for a class, and I'm trying to apply a gradient to a sphere, but (obviously), I can't figure out how to do it. I'm stuck because I know that a sphere is an object, and so it needs to have a material, but (as far as colors go), a PhongMaterial only takes one color, and so it won't take a gradient because a gradient is a range of colors. So basically what I'm trying to is the following:
Sphere sphere = new Sphere(50);
RadialGradient rg = new RadialGradient(0, 0, 0, 0, 5, true, CycleMethod.REPEAT, /*arbitrary/irrelevant color Stop objects*/));
PhongMaterial pm = new PhongMaterial();
pm.setDiffuseMap(pm);
sphere.setMaterial(asdf);
Now obviously this code doesn't work, but I guess it's the idea/flow of what I'm trying to do.
回答1:
You are right about one thing, PhongMaterial
takes a Color
as diffuse color, and that doesn't allow a Gradient
. For that, it should accept Paint
, but that is not the case.
So we have to look for different alternatives.
DiffuseMap
If you check PhongMaterial
, you can set the diffuse map with an image. That means that you can use an existing image with some gradient and apply it to the sphere.
Something like this:
Sphere sphere = new Sphere(100);
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(new Image("http://westciv.com/images/wdblogs/radialgradients/simpleclorstops.png"));
sphere.setMaterial(material);
will produce the following result:
Dynamic DiffuseMap
Obviously, this has the disadvantage of depending on a static image. What if you want to modify that dynamically?
You can do that, if you generate your radial gradient, render it on a secondary scene and take a snapshot of it. This snapshot returns a WritableImage
that you can use directly as diffuse map.
Something like this:
Scene aux = new Scene(new StackPane(), 100, 100,
new RadialGradient(0, 0, 0.5, 0.5, 1, true, CycleMethod.REPEAT,
new Stop(0, Color.GREEN), new Stop(0.4, Color.YELLOW),
new Stop(0.6, Color.BLUE), new Stop(0.7, Color.RED)));
WritableImage snapshot = aux.snapshot(null);
Sphere sphere = new Sphere(100);
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(snapshot);
sphere.setMaterial(material);
You will have now:
Density Map
There is still another option to use a mathematical function to generate a density map, and the colors will be given by a mapping to that function.
For that you can't use the built-in Sphere
, but you have to either create your own TriangleMesh
and play with the texture coordinates, or you can simply use FXyz, an open source JavaFX 3D library with a number of different primitives and texture options.
For this case, you can get the library from Maven Central (org.fxyz3d:fxyz3d:0.3.0
), use a SegmentedSphereMesh
control, and then select the texture mode `Vertices3D:
SegmentedSphereMesh sphere = new SegmentedSphereMesh(100);
sphere.setTextureModeVertices3D(1530, p -> p.z);
Note the function in this case is just based on the z
coordinate, but obviously you can modify that as needed.
Check the library (there is a sampler), to explore other options.
来源:https://stackoverflow.com/questions/50976389/apply-gradient-to-sphere-object-with-javafx