Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 3 of 3

Thread: Multi-Texture Terrain

  1. #1
    Newbie Newbie
    Join Date
    May 2018
    Posts
    1

    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

    Code :
    #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?

  2. #2

  3. #3
    Junior Member Newbie
    Join Date
    May 2018
    Posts
    11
    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:

    Code :
    #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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •