Custom TerrainPatch (Detailed) Help


#25

Ignore. Got the tree part working. Thanks for listening.

I have to figure out size(length) based on depth level


#26

Hey,

I got the tree working.

https://imgur.com/g41wCZe

Right now, I’m trying to figure out how to properly update depth. The way the tree works is there is the main object, a node for the face, then nodes with children or patch. The bounding box adds all the triangles of a patch in a polyhedron then the bounding box is set.

I currently set the maximum depth, but I want to properly calculate the max depth. Before I get the real time worked on. I want to set it up, so a max depth is pre-calculated building the geometry, it’s created based 0 depth. Then recalculated on the first UpdateBatch using the camera distance. Which updates the parent main node. The first build sense it would be depth 0 would be really fast.

The issue is how do I properly use the batches[x].loddistance_ to determine the depth level if the terrain is spherical. I would think on the urho3d post update the main terrain node / logic component would have to calculate depth using the information from the patches to rebuild the geometry if need be.

void TerrainPatch::UpdateBatches(const FrameInfo& frame)
{
    const Matrix3x4& worldTransform = node_->GetWorldTransform();
    distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());

    float scale = worldTransform.Scale().DotProduct(DOT_SCALE);
    lodDistance_ = frame.camera_->GetLodDistance(distance_, scale, lodBias_);

    batches_[0].distance_ = distance_;
    batches_[0].worldTransform_ = &worldTransform;

    unsigned newLodLevel = 0;
    for (unsigned i = 0; i < lodErrors_.Size(); ++i)
    {
        if (lodErrors_[i] / lodDistance_ > LOD_CONSTANT)
            break;
        else
            newLodLevel = i;
    }

    lodLevel_ = GetCorrectedLodLevel(newLodLevel);
}

#27

Have anyone written a simple shader? Super basic that can take light a object then changes a color using the mixfunction? Basically I have to create a shader that lerp between some values, and apply a texture based on the height radius from some point to vertex point.

#include "Uniforms.glsl"
#include "Samplers.glsl"
#include "Transform.glsl"
#include "ScreenPos.glsl"
#include "Lighting.glsl"


// Passed values
varying vec3 vNormal;
varying vec4 vWorldPos;


// vertex shasder
void VS()
{
   // Get matrix
   mat4 modelMatrix = iModelMatrix;

   // Get world position
   vec3 worldPos = GetWorldPos(modelMatrix);

   // Get position (Clipped)
   gl_Position = GetClipPos(worldPos);  

   // Get vector world position depth
   vWorldPos = vec4(worldPos, GetDepth(gl_Position));
   
   // Get Noraml
   vNormal = GetWorldNormal(modelMatrix);  
}


// pixel shader
void PS()
{
  //  variables
  vec3 lightColor;
  vec3 lightDir;
  vec3 finalColor;

  // Normalize the vNormal
  vec3 normal = normalize(vNormal);  

  // set color
  vec4 diffColor = vec4(1.0, 0.0, 0.0, 1.0);


  // NOTE:
  // I think to use to mix the color I would use the normal. Distance vector4.0 to world position should be good 
  // but when using it. There was no gradient.

  // diffColor = mix(vec4(0.0,1.0f,0.0f,1.0f), vec4(1.0f,1.0f,1.0f,1.0f), distance(vec4(0.0f,0.0f,0.0f,0.0f), vWorldPos));

  // get diff using world position and light direction amount
  float diff = GetDiffuse(normal, vWorldPos.xyz, lightDir);

  // light color based on current light color
  lightColor = cLightColor.rgb;

  // final color equal diff amount times light color * diffcolor
  finalColor = (diff * lightColor) * diffColor.rgb;

  // fog color equals final color and fog factor of 0
  gl_FragColor = vec4(finalColor, diffColor.a);	

}


#28

You need to normalize your distance into something usable ((vertDist - minDist) / (maxDist - minDist)), your distance was probably way outside of a usable 0-1 range.

I’d look up the color from a ramp texture, can be authored in Photoshop/Gimp using the gradient map modifier. Though there are simple gradient techniques (quilez’ cos tables) they’re probably not going to have the range or control you want for serious use. You can also pack gradient LUTs into one texture for specifying which LUT to use in a uniform.


#29

Yes. I figured that also. I’m thinking that a heightmap texture would help and that is passed to the shader. I’ve used that method before in older code.

The only hiccup I have now is somehow calculating the normals better without using a texture.

and also since I’m using the triangle list it’s a memory hog although for subdividing terrain the way I need. I think triangle list of creation is best.


#30

I would love to see this somehow combined with @JTippettsterrain editor, btw. :slight_smile:
A future UrhoEdit could include this planet builder.


#31

That would be cool including the spherical gravity.


#32

I’m trying to create a texture but it’s failing. Ideally, I would like to make a single channel texture if possible.

	// Create memory
	m_pHeightMapTextureData = new float[TEXELSIZEPLUS *TEXELSIZEPLUS*4];

	// Create off texture turn off compression
	m_pHeightMapTexture->SetNumLevels(1);
	m_pHeightMapTexture->SetSize(TEXELSIZEPLUS, TEXELSIZEPLUS, CF_RGBA, TEXTURE_STATIC);
	m_pHeightMapTexture->SetData(0, 0, 0, TEXELSIZEPLUS, TEXELSIZEPLUS,
				m_pHeightMapTextureData);
	m_pHeightMapTexture->SetFilterMode(FILTER_NEAREST);

#33

I tried the two following codes. I get a segfault.

I changed the code to

// Create memory
	m_pHeightMapTextureData = new float[TEXELSIZEPLUS *TEXELSIZEPLUS];

	// Create off texture turn off compression
	m_pHeightMapTexture->SetNumLevels(1);
	m_pHeightMapTexture->SetSize(TEXELSIZEPLUS, TEXELSIZEPLUS, GL_RGBA32F, TEXTURE_STATIC);
	m_pHeightMapTexture->SetData(0, 0, 0, TEXELSIZEPLUS, TEXELSIZEPLUS,
				m_pHeightMapTextureData);
	m_pHeightMapTexture->SetFilterMode(FILTER_NEAREST);

Attempt 2

// Create memory
	//m_pHeightMapTextureData = new float();

	// Create off texture turn off compression
	m_pHeightMapTexture->SetNumLevels(1);
	m_pHeightMapTexture->SetSize(TEXELSIZEPLUS, TEXELSIZEPLUS, GL_RGBA32F, TEXTURE_DYNAMIC);
	m_pHeightMapTexture->SetFilterMode(FILTER_NEAREST);

 	m_pHeightMapTexture->GetData(0, m_pHeightMapTextureData);

#34

Looks like you dropped that 4. You said you want single-channel but you’re specifying GL_RGBA32F which expects 4 floats per pixel - not 1, you probably want GL_R32F.


You should be using the helper functions in Graphics for Graphics::GetFloat32Format(), Graphics::GetRGBAFormat(), etc. If you use those you can be reasonably sure that the code handles them and they’re less eye-glaze inducing than the DXGI / GL_ formats.

If you specify arbitrary formats you’re counting on Texture::GetRowDataSize(int) actually having a case for the format you pass. If it’s not there then setting texture data will silently fail as you’re trying to apply 0-length data.


#35

Yea. I was comparing the OpenGL syntax to describe the float 32bit. I wasn’t too sure of the Urho3D equivalent. “[TexelSize]x[Texelsize]x4” was a bit excessive. Ideally, I would rather just keep the pointer on Urho3D side and unload all the data onto the GPU.

The next thing I have to tackle is getting some good normals so the triangles aren’t showing obviously that want be excessive till I can get the GPU to generate the normals.


#36

I’ll probably figure this out but does anyone on the shader side get a position on a texture from a vector3? My next step on the shader is passing the generated heightmap per patch and do a gradient. After adding some uv, for triplanar texturing.

While I do more optimizing and clean up.


#37

The other question I have is about the shader.

If a texture is passed to a shader. If I use the shader for another patch. Wouldn’t both share the same texture? Or is there a way to assign the different texture.
I think something like this would be enougth,


void SphereTerrainPatch::SetMaterial(Material * material) {

	// Clone material
	m_pMaterial = material->Clone();

	// Set Texture
	m_pMaterial->SetTexture(TU_CUSTOM1, m_pTopology->GetHeightMap());

	// set material
	for (unsigned i = 0; i < batches_.Size(); ++i)
		batches_[i].material_ = m_pMaterial;
}

#38

For a more even distribution of vertices one should use a rhombic triacontahedron instead of a cube as the base solid. It would be formed by 30 patches instead of 6, each with 8 neighboring patches instead of 4.