Cut terrain to circle?

Hello i have question with panda3d, can i cut terrain ?
by default when I load a terrain it has the shape of a square, can i cut this terrain for generate circle ?

i want use this heightmap :

with 2 terrain for generate planete, but i have square, i want to “transform” square to circle

my python code, besed of panda3d sample

#!/usr/bin/env python

from direct.showbase.ShowBase import ShowBase
from panda3d.core import ShaderTerrainMesh, Shader, load_prc_file_data
from panda3d.core import SamplerState


class ShaderTerrainDemo(ShowBase):
    def __init__(self):

        # Load some configuration variables, its important for this to happen
        # before the ShowBase is initialized
        load_prc_file_data("", """
            textures-power-2 none
            gl-coordinate-system default
            window-title Panda3D ShaderTerrainMesh Demo
        """)

        # Initialize the showbase
        ShowBase.__init__(self)

        # Increase camera FOV as well as the far plane
        self.camLens.set_fov(90)
        self.camLens.set_near_far(0.1, 50000)

        # Construct the terrain
        self.terrain_node = ShaderTerrainMesh()

        # Set a heightfield, the heightfield should be a 16-bit png and
        # have a quadratic size of a power of two.
        self.terrain_node.heightfield = self.loader.loadTexture("heightfield.png")

        # Set the target triangle width. For a value of 10.0 for example,
        # the terrain will attempt to make every triangle 10 pixels wide on screen.
        self.terrain_node.target_triangle_width = 10.0

        # Generate the terrain
        self.terrain_node.generate()

        # Attach the terrain to the main scene and set its scale. With no scale
        # set, the terrain ranges from (0, 0, 0) to (1, 1, 1)
        self.terrain = self.render.attach_new_node(self.terrain_node)
        self.terrain.set_scale(1024, 1024, 100)
        self.terrain.set_pos(-512, -512, -70.0)

        # Set a shader on the terrain. The ShaderTerrainMesh only works with
        # an applied shader. You can use the shaders used here in your own application
        terrain_shader = Shader.load(Shader.SL_GLSL, "terrain.vert.glsl", "terrain.frag.glsl")
        terrain_shader = Shader.load(Shader.SL_GLSL, "terrain.vert.glsl", "terrain_tex_f.glsl")
        self.terrain.set_shader(terrain_shader)
        
        
        
        
        # Construct the terrain
        self.terrain_node2 = ShaderTerrainMesh()

        # Set a heightfield, the heightfield should be a 16-bit png and
        # have a quadratic size of a power of two.
        self.terrain_node2.heightfield = self.loader.loadTexture("heightfield.png")

        # Set the target triangle width. For a value of 10.0 for example,
        # the terrain will attempt to make every triangle 10 pixels wide on screen.
        self.terrain_node2.target_triangle_width = 10.0

        # Generate the terrain
        self.terrain_node2.generate()

        # Attach the terrain to the main scene and set its scale. With no scale
        # set, the terrain ranges from (0, 0, 0) to (1, 1, 1)
        self.terrain2 = self.render.attach_new_node(self.terrain_node2)
        self.terrain2.set_scale(1024, 1024, 100)
        self.terrain2.set_pos(-512, 512, -70.0)
        self.terrain2.setHpr(0,180,0)

        # Set a shader on the terrain. The ShaderTerrainMesh only works with
        # an applied shader. You can use the shaders used here in your own application
        self.terrain2.set_shader(terrain_shader)
        
        
        
        
        
        self.terrain.set_shader_input("camera", self.camera)
        self.terrain2.set_shader_input("camera", self.camera)
        # Shortcut to view the wireframe mesh
        self.accept("f3", self.toggleWireframe)

ShaderTerrainDemo().run()

This could easily be done by discarding fragments. For example, to cut out a pure circle, add this to the top of the fragment shader’s main() function:

  vec2 from_center = terrain_uv - vec2(0.5);
  if (dot(from_center, from_center) > 0.25) {
    discard;
  }

Change 0.25 to alter the radius of the circle.

Or, you could discard all fragments that are entirely black in the heightmap, using something like this:

  float height = texture(ShaderTerrainMesh.heightfield, terrain_uv).x;
  if (height <= 0.0) {
    discard;
  }
1 Like

thank you very musch it’s work

final render :

There is a small problem to join the 2 maps :hushed: but I weigh that it comes from my heightmap image

If you’re trying to do planetary rendering, this is not the best approach, because the distortion is worst along the seams as you’ve noticed.

Instead, I would suggest that you take a normal heightmap, and change the vertex shader to interpret the coordinates as polar coordinates to map them to a sphere.

1 Like

If you’re trying to do planetary rendering

Yes

I don’t understand your solution, you mean with only 1 heightmap and only 1 terrain I can make a platenet?
like this :

Yes, though it would appear that ShaderTerrainMesh is not very well suited for this. It would be possible to create a sphere model with UV coordinates that map a heightmap to it (similar to the Mercator projection), and use that for sampling the height in the shader. Instead of the height affecting the z of each vertex, it would affect the distance between the vertex to the sphere’s centre.

In panda3d for create heightmap with affect z axis i use :
self.terrain_node.heightfield

for affect the sphere centre, what function must be use ?