Multi-Texture Terrain

First of all i’m learning OpenGL so pls try to not get super technical/deep xD

Ok, i’m creating a terrain, but i need it to use multi-texture (it doesn’t matter if it’s based on the height, or on a draw or something), and i found this

#include "Terrain.h"
#include "TextureLoader.h"

Terrain::Terrain(int size, char* height_map_texture_path, char* texture_path, char* texture_path2)
{
	this->size = size;
	this->texture[1] = LoadTextureTerrain(texture_path2);
	
	this->texture[0] = LoadTextureTerrain(texture_path);
	LoadVertex(height_map_texture_path);
}

Terrain::~Terrain()
{
	delete this->height_map;
	glDeleteTextures(2, this->texture);
}

void Terrain::LoadVertex(char* height_map_texture_path)
{
	AUX_RGBImageRec *TextureImage[1];
	memset(TextureImage, 0, sizeof(void *)*1);
	TextureImage[0] = auxDIBImageLoad(height_map_texture_path);
	
	sizeX= TextureImage[0]->sizeX;
	sizeY= TextureImage[0]->sizeY;

	this->height_map = new GLubyte[sizeX * sizeY];

	for(unsigned int i = 0; i < sizeY; i++)
	{
		for(unsigned int j = 0; j < sizeX; j++)
		{
			height_map[(i * sizeX + j)] = TextureImage[0]->data[(i * sizeX + j) * 3];
		}
	}
}

void Terrain::Draw()
{
	float scaleFactor = 1.5f;
	float maxHeight = 30.0;

	glPushMatrix();
	//glScalef(0.2f, 0.2f, 0.2f);
	glPushAttrib(GL_TEXTURE_BIT);

		int avg_size = (sizeX + sizeY) / 2;

		for(int z = 0; z < sizeY - 1; ++z)
		{
			glBegin(GL_TRIANGLE_STRIP);
			for (int x = 0; x < sizeX; ++x)
			{
				float scaledHeight = height_map[z * avg_size + x] / scaleFactor;
				float nextScaledHeight = height_map[(z + 1) * avg_size + x] / scaleFactor;

				float color = 0.5f + 0.5f * scaledHeight / maxHeight;
				float nextColor = 0.5f + 0.5f * nextScaledHeight / maxHeight;
			  


				glColor4f(color, color, color, 1.0f);
				glTexCoord2f(((float)x / (float)sizeX), ((float)z / (float)sizeY));//TEXTURE COMPLETE
				//glTexCoord2f(((float)x / (float)size * 5.0f), ((float)z / (float)size * 5.0f));//TEXTURE REPEAT
				glVertex3f( (float)(((float)x/(float)sizeX)*size - (size / 2.0f)), scaledHeight, (float)(((float)z/(float)sizeY)*size - (size / 2.0f)));
			  
				glColor4f(nextColor, nextColor, nextColor, 1.0f);
				float numero = (float)((float)(x + 1) / (float)size);
				glTexCoord2f(((float)(x + 1) / (float)sizeX), ((float)(z + 1) / (float)sizeY));//TEXTURE COMPLETE
				//glTexCoord2f(((float)x / (float)size * 5.0f), ((float)(z + 1) / (float)size * 5.0f)); //REPEAT TEXTURE
				glVertex3f((float)(((float)x/(float)sizeX)*size - (size / 2.0f)), nextScaledHeight, (float)(((float)(z+1)/(float)sizeY)*size - (size / 2.0f)));
			}
			glEnd();
		}
	glPopAttrib();
	glPopMatrix();
}

so it worked to put a terrain, and i’m also using a function that i founded on internet to put a texture to it, but, how can i change it so that i can put two textures in it?

you can refer to this article https://ferransole.wordpress.com/2014/06/09/array-textures/

First of all, never ever use code that you found somewhere on the internet, whether it’s Stackoverflow or something else. You don’t know which side effects it causes, which assumptions where made in order to make it work, what’s running in the background, possible memory leaks etc.

That being said, you basically need 3 textures: Two textures that are used to paint the terrain and the third one is a splat map. The splat map has the same dimensions than your terrain and stores the weights that are used to blend between the first 2 textures. In your fragment shader, you can do something like this:


#version 330
layout (location = 0) out vec3 fragmentColor;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D splat_map;
uniform vec2 frequency;
in vec2 uv;
void main()
{
  fragmentColor = mix(texture(tex0, uv * frequency).rgb, texture(tex1, uv * frequency).rgb, texture(splat_map, uv).r);
}

To actually render the terrain, you can simply render a single grid, or you look out for more advanced solutions like geo mip mapping and terrain tessellation. And I recommend not to use immediate mode commands, they are deprecated.