I generated a terrain from a heightmap and now I'd like to apply shader on it which can contain different textures, based on height but I can't adapt any online code to my project. This is the GL_LINE rendered image
The matrix generated from the heightmap has 0-255 values and -1 as the endline character.
This is the code of the terrain, the matrix is stored in a map
structure:
#include "Terrain.h"
Terrain::Terrain(Scene* s, string filename): Entity(s) {
this->hm = s->getHeightmap(filename);
texture = scene->getTexture("avatar2.jpg");
shader = scene->getShader("terrain.shader");
}
Terrain::~Terrain() {
}
void Terrain::draw() {
cout << "Draw Terrain" << endl;
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
//glUseProgramObjectARB(0);
glUseProgram(this->shader->getRes());
glTranslated(0, -20, -31.4);
glRotatef(45, -1, 0, 0);
const float offX = -25;
const float offY = 0;
const float lato = 0.5;
const int limit = 100;
const int limsx = 0;
glBegin(GL_QUADS);
for (float i = limsx; i < limit-1; ++i) {
for (float j = limsx; j < limit-1; ++j) {
glVertex3f(offX+lato*(j+1), offY+lato*i, hm->getHeight(i,j+1)/50);
glVertex3f(offX + lato*(j + 1), offY + lato*(i + 1), hm->getHeight(i + 1, j+1)/50);
glVertex3f(offX + lato*j, offY + lato*(i + 1), hm->getHeight(i+1, j)/50);
glVertex3f(offX + lato*j, offY + lato*i, hm->getHeight(i, j)/50);
}
}
glEnd();
}
Can you help me generating a terrain shader? Thank you very much
EDIT: thanks a lot to sakul_ca. This is what I got by using and editing his code
I used a shader that applies 4 textures to different heightmap values
Answer
To give you exactly what you are asking for, look at the bottom two code examples.
To use those code examples, there are other code examples preceding it. These examples are using Vertex Buffer Objects. Which is something you should start using, and not "glBegin/glVertex/glEnd", because those are all deprecated OpenGL functions.
You are asking for multiple textures in your question too. You can do that by adding another texture with the shaders, and set them in the appropriate places in the C++ code.
Load Function
void LoadModel ( void )
{
// ...
// 1. Load the model from file.
// 2. Get model information
// - Number of vertices
// - Texture coordinates
// 3. Make Data information
// - e.g.
// - Vertex_p4t4* pTempVertArray = new Vertex_p4t4[numVertices *2];
// - GLuint* pIndexArrayLocal = new GLuint[numIndicesInIndexArray * 2];
// ...
GLuint vboID;
glGenVertexArrays( 1, &vboID );
// Check for OpenGL error.
glBindVertexArray( vboID );
// Check for OpenGL error.
// [SimpleTextureShader.vertex.glsl]
// layout (location=0) in vec4 in_Position
// layout (location=1) in vec4 in_UVx2;
glEnableVertexAttribArray ( 0 );
glEnableVertexAttribArray ( 1 );
// Check for OpenGL error.
GLuint vertexBufferID;
GLuint indexBufferID;
glGenBuffers ( 1, &vertexBufferID );
glGenBuffers ( 1, &indexBufferID );
// Check for OpenGL error.
glBindBuffer ( GL_ARRAY_BUFFER, vertexBufferID );
// Check for OpenGL error.
// In this case [sizeof ( YOURVERTEXDATA )] = 32)
unsigned int vertSize = sizeof ( YOURVERTXDATA );
unsigned int size = numVerticesInModel * vertSize ;
glBufferData ( GL_ARRAY_BUFFER, size, VERTEXDATA, GL_STATIC_DRAW );
// Check for OpenGL error.
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, vertSize, 0 );
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, vertSize, 16 );
// Check for OpenGL error.
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, indexBufferID );
// Check for OpenGL error.
glBufferData ( GL_ELEMENT_ARRAY_BUFFER, TOTALSIZEINBYTES, pIndexArrayLocal, GL_STATIC_DRAW);
// Check for OpenGL error.
glBindVertexArray( 0 );
// Check for OpenGL error.
// ...
// Delete things you don't need anymore
// ...
// Add model information to wherever you want
// ...
return;
}
Render Function
void Render ( void )
{
// Set the texture shader program
glUseProgram(currentProgramID);
// uniform mat4 ModelMatrix;
// uniform mat4 ViewMatrix;
// uniform mat4 ProjectionMatrix;
// uniform sampler2D texture_0;
// Normally you would get this information when loading the shader, and save all of the data somewhere else instead of getting it every time you render.
GLint ModelMatrixUniformLocation = getUniformLocation ( currentShaderProgramID, "ModelMatrix" );
GLint ViewMatrixUniformLocation = getUniformLocation ( currentShaderProgramID, "ViewMatrix" );
GLint ProjectionMatrixUniformLocation = getUniformLocation ( currentShaderProgramID, "ProjectionMatrix" );
GLint Texture0UniformLocation = getUniformLocation ( currentShaderProgramID, "texture_0" );
// I'm using glm for this example, you can use whatever math library you wish, or write your own.
// Create a model matrix to use
glm::mat4 matModel = glm::mat4( 1.0f ); // initialize as identity;
// Create a view matrix to use
glm::mat4 matView = glm::lookAt(eye, look, up);
// Create a projection matrix to use
glm::mat4 matProj = glm::perspective( fovy, aspect, zNear, zFar );
// OpenGL does matrix Transformation Calculations backwards, so you want to do:
// Post Rotation, Translating, Pre Rotation, Scale
// We are only translating in this example
matMode = matMode = glm::translate ( matMode, ObjectPosition );
// Send the matrix values to the shader program
glUniformMatrix4fv( ModelMatrixUniformLocation, 1, GL_FALSE, glm::value_ptr ( matModel ));
glUniformMatrix4fv( ViewMatrixUniformLocation, 1, GL_FALSE, glm::value_ptr ( matView));
glUniformMatrix4fv( ProjectionMatrixUniformLocation, 1, GL_FALSE, glm::value_ptr ( matProj));
// Send the texture information to the shader program
glActiveTexture(textureEnum);
// Check for OpenGL error.
glBindTexture(GL_TEXTURE_2D, textureID);
// Check for OpenGL error.
glUniform1i ( Texture0UniformLocation, textureID );
// Check for OpenGL error.
// Render your object(s) [ vboID from LoadTexture function ]
glBindVertexArray ( vboID );
// Check for OpenGL error.
unsigned int numberOfIndices = NumberOfTrianglesInMesh * 3;
glDrawElements ( GL_TRIANGLES, numberOfIndices, GL_UNSIGNED_INT, (GLvoid*)0 );
// Check for OpenGL error.
// All done
return;
}
SimpleTextureShader.vertex.glsl
#version 400
layout (location=0) in vec4 in_Posiiton;
layout (location=1) in vec4 in_UVx2;
out vec4 ex_Position;
out vec4 ex_UVx2;
uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
void main ( void )
{
mat4 MVPMatrix = ProjectionMatrix * ViewMatrix * ModelMatrix;
gl_Position = MVPMatrix * in_Position;
ex_Position = gl_Position;
ex_UVx2 = in_UVx2;
return;
}
SimpleTextureShader.fragment.glsl
#version 400
// From the vertex shader
in vec4 ex_Position;
in vec4 ex_UVx2;
// Texture information
uniform sampler2D texture_0;
// If you want multiple textures...
// uniform samples2D texture_1;
// uniform samples2D texture_2;
// uniform samples2D texture_3;
// ...
void main ( void )
{
vec4 colour = vec4 ( 0.0f, 0.0f, 0.0f, 0.0f );
colour = texture( texture_0, ex_UVx2.xy );
// if you want multiple textures...
// vec4 texture1Colour = texture( texture_1, ex_UVx2.xy );
// vec4 texture2Colour = texture( texture_2, ex_UVx2.xy );
// vec4 texture3Colour = texture( texture_3, ex_UVx2.xy );
// Then do what you want with them.. e.g.
// vec4 tex1Times2 = texture1Colour * texture2Colour;
// vec4 texHeightColour = texture1Colour * ( 10.0f - gl_Position.y )
// texHeightColour += texture2Colour * gl_Position;
// colour= clamp ( texHeightColour, 0.0f, 1.0f );
out_Colour = colour;
return;
}
No comments:
Post a Comment