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
+ }
0 commit comments