summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2011-04-09 20:22:13 +0200
committerJon Bergli Heier <snakebite@jvnv.net>2011-04-09 20:22:13 +0200
commit3817acdb49d775edb23fafbed70095be8f648ed6 (patch)
tree088d94ebd9f767e84263e1400db336930a7324cd
parente19c3838a4d89fb0640ed563ffdf58cd125cde7f (diff)
Terrain multitexturing.
-rw-r--r--main.cpp88
-rw-r--r--quadtree.cpp7
-rw-r--r--scene.cpp7
-rw-r--r--shader.cpp4
-rw-r--r--shader.h2
-rw-r--r--shaders/terrain_fragment.glsl22
-rw-r--r--shaders/terrain_vertex.glsl (renamed from terrain_vertex.glsl)7
-rw-r--r--terrain_fragment.glsl11
8 files changed, 90 insertions, 58 deletions
diff --git a/main.cpp b/main.cpp
index 97abb46..b068cd5 100644
--- a/main.cpp
+++ b/main.cpp
@@ -20,6 +20,33 @@
FTFont *font;
+GLuint load_texture(const std::string filename) {
+ GLuint texture;
+ SDL_Surface *surface = IMG_Load(filename.c_str());
+ SDL_Surface *image = SDL_CreateRGBSurface(SDL_SWSURFACE, surface->w, surface->h, 32,
+ 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
+ SDL_Rect area;
+ area.x = area.y = 0;
+ area.w = surface->w;
+ area.h = surface->h;
+ SDL_BlitSurface(surface, &area, image, &area);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ if(image->format->Amask) {
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 4, image->w, image->h, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
+ } else {
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image->w, image->h, GL_RGB, GL_UNSIGNED_BYTE, image->pixels);
+ }
+ SDL_FreeSurface(surface);
+ SDL_FreeSurface(image);
+
+ return texture;
+}
+
+
int main(int argc, char **argv) {
video::width = 1280;
video::height = 720;
@@ -28,40 +55,27 @@ int main(int argc, char **argv) {
Scene scene;
GLShaderProgram program;
- GLVertexShader terrain_vertex("terrain_vertex.glsl");
- GLFragmentShader terrain_fragment("terrain_fragment.glsl");
+ GLVertexShader terrain_vertex("shaders/terrain_vertex.glsl");
+ GLFragmentShader terrain_fragment("shaders/terrain_fragment.glsl");
program.attach(terrain_vertex);
program.attach(terrain_fragment);
program.link();
+ {
+ program.use();
+ GLint tex1loc = glGetUniformLocation(program.get_program(), "tex[1]");
+ glUniform1i(tex1loc, 1);
+ GLint tex2loc = glGetUniformLocation(program.get_program(), "tex[2]");
+ glUniform1i(tex2loc, 2);
+ glUseProgram(0);
+ }
+
font = new FTTextureFont("font.ttf");
font->FaceSize(10);
- GLuint grass_texture;
- {
- SDL_Surface *surface = IMG_Load("Grass0073_3_S.jpg");
- SDL_Surface *image = SDL_CreateRGBSurface(SDL_SWSURFACE, surface->w, surface->h, 32,
- 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
- SDL_Rect area;
- area.x = area.y = 0;
- area.w = surface->w;
- area.h = surface->h;
- SDL_BlitSurface(surface, &area, image, &area);
- //glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glGenTextures(1, &grass_texture);
- glBindTexture(GL_TEXTURE_2D, grass_texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- if(image->format->Amask) {
- //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
- gluBuild2DMipmaps(GL_TEXTURE_2D, 4, image->w, image->h, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
- } else {
- //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image->w, image->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image->pixels);
- gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image->w, image->h, GL_RGB, GL_UNSIGNED_BYTE, image->pixels);
- }
- SDL_FreeSurface(surface);
- SDL_FreeSurface(image);
- }
+ GLuint grass_texture = load_texture("textures/Grass0073_3_S.jpg");
+ GLuint rock_texture = load_texture("textures/RockJagged0010_2_S.jpg");
+ GLuint soil_texture = load_texture("textures/SoilSand0168_9_S.jpg");
//SDL_WM_GrabInput(SDL_GRAB_ON);
@@ -207,9 +221,17 @@ int main(int argc, char **argv) {
unsigned int chunks_rendered = 0;
if(terrain) {
program.use();
- glBindTexture(GL_TEXTURE_2D, grass_texture);
glEnable(GL_TEXTURE_2D);
- //for(int i = 0; i < scene.qt->chunk_count; i++) {
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, grass_texture);
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, rock_texture);
+
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, soil_texture);
+
std::queue<Quadtree::QuadChunk*> q;
q.push(scene.qt->root);
while(!q.empty()) {
@@ -222,25 +244,21 @@ int main(int argc, char **argv) {
} else if(!chunk->vbo_object)
continue;
chunks_rendered++;
- //std::cout << (boost::format("vertices: %d nodes: %d") % scene.qt->chunks[i]->vertices % scene.qt->chunks[i]->node_count).str() << std::endl;
- //glBindBuffer(GL_ARRAY_BUFFER, scene.qt->vbo_object);
- //glBindBuffer(GL_ARRAY_BUFFER, scene.qt->chunks[i]->vbo_object);
glBindBuffer(GL_ARRAY_BUFFER, chunk->vbo_object);
glVertexPointer(3, GL_FLOAT, 0, NULL);
- //glNormalPointer(GL_FLOAT, 0, (GLvoid*)(scene.qt->vertices*3*sizeof(float)));
glNormalPointer(GL_FLOAT, 0, (GLvoid*)(chunk->vertices*3*sizeof(float)));
- //glTexCoordPointer(2, GL_FLOAT, 0, (GLvoid*)(scene.qt->vertices*3*sizeof(float)*2));
glTexCoordPointer(2, GL_FLOAT, 0, (GLvoid*)(chunk->vertices*3*sizeof(float)*2));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- //glDrawArrays(GL_TRIANGLES, 0, scene.qt->vertices);
glDrawArrays(GL_TRIANGLES, 0, chunk->vertices);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glDisable(GL_TEXTURE_2D);
+ // set active to texture0 to avoid breaking the texture font
+ glActiveTexture(GL_TEXTURE0);
glUseProgram(0);
}
if(grid) {
diff --git a/quadtree.cpp b/quadtree.cpp
index 1f2dd4a..8bc366c 100644
--- a/quadtree.cpp
+++ b/quadtree.cpp
@@ -1,9 +1,6 @@
#include "quadtree.h"
#include "vector.h"
-#include <boost/format.hpp>
-#include <boost/timer.hpp>
-
#include "gl.h"
#include <cmath>
@@ -333,7 +330,6 @@ Quadtree::Quadtree(int width, int height, float *heightmap) {
root = new QuadChunk(this, 0, 0, width-1, height-1);
- boost::timer t;
normals = new Vector3[width*height];
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
@@ -362,12 +358,9 @@ Quadtree::Quadtree(int width, int height, float *heightmap) {
N += V.cross(U);
}
}
- if(N.y < 0)
- std::cout << N.str() << std::endl;
normals[x*height + y] = N / N.length();
}
}
- std::cout << "normal time: " << t.elapsed() << std::endl;
}
Quadtree::~Quadtree() {
diff --git a/scene.cpp b/scene.cpp
index d6cfd80..199471f 100644
--- a/scene.cpp
+++ b/scene.cpp
@@ -8,7 +8,7 @@
#define inrange(a, b, c) ((a) >= (b) && (a) <= (c))
Scene::Scene() {
- SDL_Surface *hm = IMG_Load("heightmap10.png");
+ SDL_Surface *hm = IMG_Load("heightmap.png");
float *heightmap = new float[hm->w * hm->h];
for(int x = 0; x < hm->w; x++) {
for(int y = 0; y < hm->h; y++) {
@@ -28,6 +28,7 @@ Scene::~Scene() {
}
void Scene::lookat() {
+ const float cam_height = 1.7;
/* calculate cartesian coordinates for the center vector where yaw is Φ and pitch is θ
* x = cos Φ sin θ
* y = cos θ
@@ -35,10 +36,10 @@ void Scene::lookat() {
*/
Vector3 center(sinf(pitch) * cosf(yaw), cosf(pitch), sinf(pitch) * sinf(yaw));
center += pos;
- center.y += 1;
+ center.y += cam_height;
//Vector3 up(cosf(yaw) * cosf(pitch), sinf(pitch), sinf(yaw) * cosf(pitch));
Vector3 up(-cosf(pitch) * cosf(yaw), sinf(pitch), -cosf(pitch) * sinf(yaw));
- gluLookAt(pos.x, pos.y+1, pos.z,
+ gluLookAt(pos.x, pos.y+cam_height, pos.z,
center.x, center.y, center.z,
up.x, up.y, up.z);
}
diff --git a/shader.cpp b/shader.cpp
index 8d3493e..06943f0 100644
--- a/shader.cpp
+++ b/shader.cpp
@@ -92,3 +92,7 @@ void GLShaderProgram::use() {
gl_check_error("Failed to use program");
}
+
+GLuint GLShaderProgram::get_program() {
+ return program;
+}
diff --git a/shader.h b/shader.h
index 1e11028..d9bfff0 100644
--- a/shader.h
+++ b/shader.h
@@ -40,6 +40,8 @@ class GLShaderProgram {
void detach(GLBaseShader&);
void link();
void use();
+
+ GLuint get_program();
};
#endif
diff --git a/shaders/terrain_fragment.glsl b/shaders/terrain_fragment.glsl
new file mode 100644
index 0000000..78417af
--- /dev/null
+++ b/shaders/terrain_fragment.glsl
@@ -0,0 +1,22 @@
+#version 120
+
+varying vec3 normal, light_pos;
+varying float y;
+
+uniform sampler2D tex[3];
+
+void main() {
+ vec3 n = normalize(normal);
+ float diffuse = max(dot(n, light_pos), 0.0);
+
+ float f1 = clamp((y-15.0) / 3.0, 0.0, 1.0);
+ float f2 = clamp((y-2) / 3.0, 0.0, 1.0);
+
+ vec4 t0 = texture2D(tex[0], gl_TexCoord[0].st);
+ vec4 t1 = texture2D(tex[1], gl_TexCoord[0].st);
+ vec4 t2 = texture2D(tex[2], gl_TexCoord[0].st);
+
+ gl_FragColor = mix(mix(t2, t0, f2), t1, f1) * diffuse;
+}
+
+/* vim: set syn=glsl: */
diff --git a/terrain_vertex.glsl b/shaders/terrain_vertex.glsl
index 8bb21d0..e53c432 100644
--- a/terrain_vertex.glsl
+++ b/shaders/terrain_vertex.glsl
@@ -1,9 +1,12 @@
-varying vec3 normal, light_pos, V, N;
-varying vec4 diffuse, ambient;
+#version 120
+
+varying vec3 normal, light_pos;
+varying float y;
void main() {
normal = gl_Normal;
light_pos = vec3(0, 1, 0);
+ y = gl_Vertex.y;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
diff --git a/terrain_fragment.glsl b/terrain_fragment.glsl
deleted file mode 100644
index 774bfd3..0000000
--- a/terrain_fragment.glsl
+++ /dev/null
@@ -1,11 +0,0 @@
-varying vec3 normal, light_pos;
-
-uniform sampler2D tex;
-
-void main() {
- vec3 n = normalize(normal);
- float diffuse = max(dot(n, light_pos), 0.0);
- gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * diffuse;
-}
-
-/* vim: set syn=glsl: */