I want to adjust the size of the plane mesh according to the camera view in the 3D scene, that is, how big an area does the camera see in x and z coordinates, how do I calculate this or is there a ready-made function?

  • xyz replied to this.

    xyz When we first open the 3D scene editor, there is a grid-like surface appearance, I will try to get that kind of appearance.

    • xyz replied to this.

      xyz I thought it could be done with the logic of infinite terrain. What is your opinion about this and how to do such a thing?

      
      using Godot;
      using NuGet.Configuration;
      using System;
      
      public partial class SquareFloor : Node3D
      {
      	Camera3D Cam;
      	Vector3 PlaneNormal;
      	//float PlaneDistance;
      	Godot.Collections.Array<Plane> Vectorfrust;
      	ImmediateMesh DrawMesh;
      	MeshInstance3D MeshSet;
      	Vector3? IntersectionPoint;
      	// Called when the node enters the scene tree for the first time.
      	public override void _Ready()
      	{
      		Cam = GetNode<Camera3D>("Camera3D");
      		MeshSet = new MeshInstance3D();
      		AddChild(MeshSet);
      		DrawMesh = new ImmediateMesh();
      		//MeshSet.Mesh = DrawMesh;
      	}
      
      	// Called every frame. 'delta' is the elapsed time since the previous frame.
      	public override void _Process(double delta)
      	{
      		if (DrawMesh.GetSurfaceCount() < 250)
      		{
      			DrawPlane ();
      		}
      	}
      
      	private void DrawPlane ()
      	{
      		Vectorfrust = Cam.GetFrustum();
      		//DrawMesh.ClearSurfaces();
      		DrawMesh.SurfaceBegin(Mesh.PrimitiveType.Lines);
      		foreach (Plane plane in Vectorfrust)
      		{
      			PlaneNormal = plane.Normal;
      			//PlaneDistance = plane.D;
      			//IntersectionPoint = plane.IntersectsSegment(Vector3.Zero, PlaneNormal);
      			IntersectionPointControl(plane, Vector3.Zero, PlaneNormal);
      			IntersectionPointControl(plane, Vector3.Right, PlaneNormal);
      		}
      		DrawMesh.SurfaceSetColor(Color.FromHtml("#d4191e"));
      		DrawMesh.SurfaceEnd();
      		MeshSet.Mesh = DrawMesh;
      	}
      	private void IntersectionPointControl (Plane plane, Vector3 vec3, Vector3 plnrml)
      	{
      		IntersectionPoint = plane.IntersectsSegment(vec3, plnrml);
      		if (IntersectionPoint != null)
      		{
      			DrawMesh.SurfaceAddVertex((Vector3) IntersectionPoint);
      		}
      	}
      }

      why drawings do not appear on the screen where is my fault?

      • xyz replied to this.

        xyz If I understood correctly they want to create a construction grid. I'd consider array mesh for it.

          for something more brain-dead, try using a big fat plane mesh with a repeating texture, and three additional meshes for the colored axis.

            Megalomaniak If I understood correctly they want to create a construction grid. I'd consider array mesh for it.

            The original question looks closer to how to fit something into camera frustum. Then out of the blue it mutated into grid construction... that I suspect needs fitting into camera frustum? So who knows, might be anything at this point 🙂

            I want to get a grid-like plane, that's all, but it should appear whatever the position of the camera, just like in the editor 3D scene.

            packrat If the grid could be visible regardless of the position of the camera in the 3D scene, this idea would work for me.

            Megalomaniak I want to create a grid with lines in the field of view of the camera with ImmediateMesh, how do I do it.arraymesh is more complicated than ImmediateMesh.

            xyz I want to get a grid-like plane, that's all, but it should appear whatever the position of the camera, just like in the editor 3D scene.

            • xyz replied to this.

              unicornlox Grids like that are not drawn on planes in the world. Instead they are procedurally projected by a fragment shader onto a camera facing quad covering the entire viewport. The approach is described here. It's similar to how the procedural skyboxes are rendered.

              unicornlox
              Here's the shader. It will project "ground grid" to any piece of geometry. It just uses geometry as a silhouette to render pixels. It will write the depth value as well making the grid always appear on ground no matter where the geometry is.

              To make the grid always visible, regardless of camera position/orientation, parent a quad or a 3D sprite to the camera so that it faces the camera and covers the whole view, and assign the shader to it.

              shader_type spatial;
              render_mode blend_mix,depth_draw_opaque, unshaded;
              uniform vec4 albedo: source_color;
              uniform float fadeDistance = 100.0;
              uniform float unitSize = 1.0;
              uniform float lineThickness = 1.0;
              
              
              void fragment() {
              	// ray from camera to fragemnt in wrold space
              	vec3 rayWorld = normalize(mat3(INV_VIEW_MATRIX) * VIEW);
              	
              	// calculate fragment position in world space
              	vec3 posWorld;
              	float t = -CAMERA_POSITION_WORLD.y / rayWorld.y;
              	posWorld.y = 0.0;
              	posWorld.xz = CAMERA_POSITION_WORLD.xz + t * rayWorld.xz;
              	
              	// calculate planar distance from camera to fragment (for fading) 
              	float distPlanar = distance(posWorld.xz, CAMERA_POSITION_WORLD.xz);
              	
              	// calculate line mask, using a bit of fwidth() magic to make line width not affected by perspective
              	vec2 line = step(fwidth(posWorld.xz) * lineThickness / unitSize, fract(posWorld.xz / unitSize));
              	float lineMask = 1.0 - clamp(line.x * line.y, 0.0, 1.0);
              	
              	// eliminate grid above the horizon
              	lineMask *= step(t, 0.0);
              	// fade into distance
              	lineMask *= mix(1.0, 0.0, clamp(distPlanar/fadeDistance, 0.0, 1.0));
              	
              	// write ground plane depth into z buffer
              	vec4 pp = (PROJECTION_MATRIX * (VIEW_MATRIX * vec4(posWorld, 1.0)));
              	DEPTH = pp.z / pp.w;
              	
              	ALPHA =  lineMask * albedo.a;
              	ALBEDO = albedo.rgb;
              }

                xyz Thank you very much, I've been looking for this for days.I will try it right away.

                xyz my friend thanks a lot this is what will work for me but how do I change the shader variables with gdscript or c#, from within the code of my game? I'm talking about these variables of the shader, how can I change them?
                float fadeDistance = 100.0;
                uniform float unitSize = 1.0;

                • xyz replied to this.

                  xyz ok man I learned how to access the shader code from inside the code.

                  
                  using Godot;
                  using System;
                  
                  public partial class SquareFloor : Node3D
                  {
                  	Camera3D Cam;
                  	MeshInstance3D MeshPlaneThis;
                  	PlaneMesh MeshPlane;
                  	ShaderMaterial MeshPlaneShaderMat;
                  	//Shader MeshPlaneShader;
                  	// Called when the node enters the scene tree for the first time.
                  	public override void _Ready()
                  	{
                  		Cam = GetNode<Camera3D>("Camera3D");
                  		MeshPlaneThis = GetNode<MeshInstance3D>("MeshInstance3D");
                  		MeshPlane = (PlaneMesh) MeshPlaneThis.Mesh;
                  		MeshPlaneShaderMat = (ShaderMaterial) MeshPlane.Material;
                  		//MeshPlaneShader = MeshPlaneShaderMat.Shader;
                  		MeshPlaneShaderMat.SetShaderParameter((StringName)"fadeDistance", 100.0);
                  		MeshPlaneShaderMat.SetShaderParameter((StringName)"unitSize", 1.0);
                  	}
                  
                  	// Called every frame. 'delta' is the elapsed time since the previous frame.
                  	public override void _Process(double delta)
                  	{
                  	}
                  
                  	private void ChangeShaderParam()
                  	{}
                  }

                  unicornlox Use Material::SetShaderParameter()

                  EDIT: Ok you already figured it out.