Skip to content

Commit 111a8df

Browse files
committed
Tutorial 16 - Generación de Terrenos
Utilizar un mapa de elevación para generar un terreno, aplicamos texturas para dar mayor realismo.
1 parent 52ac689 commit 111a8df

File tree

6 files changed

+292
-0
lines changed

6 files changed

+292
-0
lines changed

Data/image/heightmap.png

36.3 KB
Loading

Data/image/terreno.jpg

137 KB
Loading

Tutorial-16/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
project(16-Terreno)
2+
3+
file(COPY terrain.vs.glsl terrain.fs.glsl DESTINATION shaders)
4+
file(COPY ../data/image/heightmap.png ../data/image/terreno.jpg DESTINATION image)
5+
6+
add_executable( ${PROJECT_NAME} terrain.cpp
7+
shaders/terrain.fs.glsl
8+
shaders/terrain.vs.glsl
9+
image/heightmap.png
10+
image/terreno.jpg
11+
../common/openglwindow.hpp
12+
../common/openglshader.hpp
13+
../common/openglcamera.hpp )
14+
15+
target_link_libraries( ${PROJECT_NAME} ${GRAPHIC_LIBS})

Tutorial-16/terrain.cpp

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
#include "OpenGLWindow.hpp"
2+
#include "OpenGLShader.hpp"
3+
#include "OpenGLCamera.hpp"
4+
5+
#define STB_IMAGE_IMPLEMENTATION
6+
#include "stb\stb_image.h"
7+
8+
#include <glm\gtc\matrix_inverse.hpp>
9+
#include <glm\gtc\matrix_transform.hpp>
10+
#include <glm\gtc\type_ptr.hpp>
11+
12+
#include <string>
13+
#include <vector>
14+
15+
class Tutorial_OpenGL_Moderno : public OpenGLWindow {
16+
17+
public:
18+
Tutorial_OpenGL_Moderno() { }
19+
20+
OpenGLCamera camera;
21+
OpenGLShader shader;
22+
23+
GLuint terrainTextureID;
24+
GLuint vao, indices_count;
25+
GLuint buffer[2];
26+
27+
private:
28+
void onstart() override {
29+
glEnable(GL_DEPTH_TEST);
30+
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
31+
32+
glClearColor(0.25f, 0.80f, 0.75f, 1.0f);
33+
34+
camera.setWindow(this->window);
35+
shader.compile("shaders/terrain.vs.glsl", "shaders/terrain.fs.glsl");
36+
37+
std::vector<GLubyte> altura;
38+
int texture_width, texture_height;
39+
loadTerrainHeight("image/heightmap.png", altura, texture_width, texture_height);
40+
createPlainTerrain(texture_width, texture_height, altura);
41+
42+
terrainTextureID = loadTerrainTexture("image/terreno.jpg");
43+
44+
glfwSetInputMode(this->window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
45+
glfwSetCursorPos(this->window, 1280 / 2, 720 / 2);
46+
}
47+
48+
void loadTerrainHeight(const std::string& filename, std::vector<GLubyte>& altura, int& width, int& height)
49+
{
50+
int channels;
51+
unsigned char *pData = stbi_load(filename.c_str(), &width, &height, &channels, STBI_grey);
52+
53+
if (pData == nullptr) {
54+
std::cout << "Error al cargar: " << filename << std::endl;
55+
return;
56+
}
57+
58+
altura.insert(altura.end(), pData, pData + (width * height));
59+
stbi_image_free(pData);
60+
}
61+
62+
63+
GLuint loadTerrainTexture(const std::string& filename)
64+
{
65+
GLuint textureID = 0;
66+
glGenTextures(1, &textureID);
67+
68+
int channels, width, height;
69+
unsigned char *pData = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb);
70+
71+
if (pData == nullptr) std::cout << "Error al cargar: " << filename << std::endl;
72+
73+
glActiveTexture(GL_TEXTURE0);
74+
glBindTexture(GL_TEXTURE_2D, textureID);
75+
76+
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);
77+
78+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
79+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
80+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
81+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
82+
83+
glBindTexture(GL_TEXTURE_2D, 0);
84+
85+
stbi_image_free(pData);
86+
87+
return textureID;
88+
}
89+
90+
void createPlainTerrain(int WIDTH, int DEPTH, std::vector<GLubyte>& altura) {
91+
92+
std::vector<glm::vec3> vertices;
93+
vertices.reserve(DEPTH * WIDTH);
94+
95+
int counter = 0;
96+
97+
for (int j = 0; j < DEPTH; j++) {
98+
for (int i = 0; i < WIDTH; i++) {
99+
float x = (float(i) / (WIDTH - 1)) * 2.0f - 1.0f;
100+
float z = (float(j) / (DEPTH - 1)) * 2.0f - 1.0f;
101+
float y = altura[counter++] / 255.0f;
102+
103+
vertices.push_back(glm::vec3(x, y, z));
104+
}
105+
}
106+
107+
std::vector<GLuint> indices((DEPTH - 1) * (WIDTH - 1) * 6);
108+
std::vector<GLuint>::iterator id;
109+
id = indices.begin();
110+
111+
for (int z = 0; z < DEPTH - 1; z++) {
112+
for (int x = 0; x < WIDTH - 1; x++) {
113+
int i0 = (z * DEPTH) + x;
114+
int i1 = i0 + 1;
115+
int i2 = ((z + 1) * DEPTH) + x;
116+
int i3 = i2 + 1;
117+
118+
*id++ = i0; *id++ = i2; *id++ = i1;
119+
*id++ = i1; *id++ = i2; *id++ = i3;
120+
}
121+
}
122+
123+
indices_count = indices.size();
124+
125+
std::vector<glm::vec3> normales(DEPTH * WIDTH);
126+
calculateNormals(normales, vertices, indices);
127+
128+
glGenVertexArrays(1, &vao);
129+
glGenBuffers(2, buffer);
130+
glBindVertexArray(vao);
131+
132+
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
133+
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
134+
glEnableVertexAttribArray(0);
135+
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
136+
137+
GLuint buffer_normal = 0;
138+
glGenBuffers(1, &buffer_normal);
139+
glBindBuffer(GL_ARRAY_BUFFER, buffer_normal);
140+
glBufferData(GL_ARRAY_BUFFER, normales.size() * sizeof(glm::vec3), &normales[0], GL_STATIC_DRAW);
141+
glEnableVertexAttribArray(1);
142+
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
143+
144+
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer[1]);
145+
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);
146+
147+
glBindVertexArray(0);
148+
}
149+
150+
void calculateNormals(vector<glm::vec3>& m_normals, vector<glm::vec3>& m_vertices, vector<GLuint>& m_indices)
151+
{
152+
for (size_t i = 0; i < m_indices.size(); i += 3)
153+
{
154+
glm::vec3 p0 = m_vertices[m_indices[i + 0]];
155+
glm::vec3 p1 = m_vertices[m_indices[i + 1]];
156+
glm::vec3 p2 = m_vertices[m_indices[i + 2]];
157+
158+
glm::vec3 e1 = p0 - p1;
159+
glm::vec3 e2 = p0 - p2;
160+
glm::vec3 normal = glm::normalize(glm::cross(e1, e2));
161+
162+
m_normals[m_indices[i + 0]] += normal;
163+
m_normals[m_indices[i + 1]] += normal;
164+
m_normals[m_indices[i + 2]] += normal;
165+
}
166+
167+
for (size_t i = 0; i < m_normals.size(); ++i)
168+
m_normals[i] = glm::normalize(m_normals[i]);
169+
}
170+
171+
void onrender(double time) override {
172+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
173+
174+
shader.use();
175+
176+
glm::mat4 M = glm::mat4(1);
177+
glm::mat4 MV = camera.getViewMatrix() * M;
178+
glm::mat4 MVP = camera.getProjectionMatrix() * MV;
179+
glm::mat3 N = glm::inverseTranspose(glm::mat3(MV));
180+
181+
glUniformMatrix4fv(shader.getUniformLocation("MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
182+
glUniformMatrix4fv(shader.getUniformLocation("MV"), 1, GL_FALSE, glm::value_ptr(MV));
183+
glUniformMatrix3fv(shader.getUniformLocation("N"), 1, GL_FALSE, glm::value_ptr(N));
184+
185+
glm::vec3 lightPosES = glm::vec3(MV * glm::vec4(10, 10, 10, 0));
186+
187+
glUniform3fv(shader.getUniformLocation("light_position"), 1, glm::value_ptr(lightPosES));
188+
glUniform3fv(shader.getUniformLocation("diffuse_color"), 1, glm::value_ptr(glm::vec3(0.75f)));
189+
190+
glActiveTexture(GL_TEXTURE0);
191+
glBindTexture(GL_TEXTURE_2D, terrainTextureID);
192+
193+
glBindVertexArray(vao);
194+
glDrawElements(GL_TRIANGLES, indices_count, GL_UNSIGNED_INT, NULL);
195+
glBindVertexArray(0);
196+
197+
glActiveTexture(GL_TEXTURE0);
198+
glBindTexture(GL_TEXTURE_2D, 0);
199+
200+
shader.unUse();
201+
}
202+
203+
void onkey(int key, int scancode, int action, int mods) override {
204+
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
205+
glfwSetWindowShouldClose(window, GL_TRUE);
206+
}
207+
208+
};
209+
210+
int main() {
211+
Tutorial_OpenGL_Moderno win_app;
212+
213+
if (win_app.init("OpenGL Moderno - Terreno", 1280, 720)) {
214+
win_app.info();
215+
216+
cout << "TOTURIALES OPENGL MODERNO - TERRENO" << endl << endl;
217+
cout << "Usar la tecla [Esc] para salir." << endl << endl;
218+
219+
win_app.run();
220+
}
221+
222+
return 0;
223+
}

Tutorial-16/terrain.fs.glsl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#version 330 core
2+
3+
out vec4 color;
4+
5+
in vec3 POS, NORMAL;
6+
in vec2 UV;
7+
8+
uniform vec3 light_position ;
9+
uniform vec3 diffuse_color;
10+
uniform sampler2D terrain;
11+
12+
void main() {
13+
vec3 N = normalize(NORMAL);
14+
vec3 L = normalize(light_position - POS);
15+
16+
float diffuse = max(0, dot(N, L));
17+
18+
//color = diffuse * vec4(diffuse_color, 1.0);
19+
color = diffuse * texture(terrain, UV);
20+
//color = vec4(1.0);
21+
}

Tutorial-16/terrain.vs.glsl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#version 330 core
2+
3+
layout(location = 0) in vec3 position;
4+
layout(location = 1) in vec3 normal;
5+
6+
uniform mat4 MVP, MV;
7+
uniform mat3 N;
8+
uniform sampler2D heightMap;
9+
10+
float scale_size = 10.0;
11+
float scale_height = 1.8;
12+
13+
out vec3 POS, NORMAL;
14+
out vec2 UV;
15+
16+
out Vertex
17+
{
18+
vec3 normal;
19+
} vertex;
20+
21+
void main()
22+
{
23+
vec2 pos = position.xz * scale_size;
24+
float height = position.y * scale_height;
25+
26+
vec4 vertex_position = vec4(pos.x, height, pos.y, 1.0);
27+
28+
gl_Position = MVP * vertex_position;
29+
30+
POS = (MV * vertex_position).xyz;
31+
NORMAL = N * normal;
32+
UV = position.xz * 0.5 + 0.5;
33+
}

0 commit comments

Comments
 (0)