diff options
author | Jon Bergli Heier <snakebite@jvnv.net> | 2011-04-09 20:22:13 +0200 |
---|---|---|
committer | Jon Bergli Heier <snakebite@jvnv.net> | 2011-04-09 20:22:13 +0200 |
commit | 3817acdb49d775edb23fafbed70095be8f648ed6 (patch) | |
tree | 088d94ebd9f767e84263e1400db336930a7324cd | |
parent | e19c3838a4d89fb0640ed563ffdf58cd125cde7f (diff) |
Terrain multitexturing.
-rw-r--r-- | main.cpp | 88 | ||||
-rw-r--r-- | quadtree.cpp | 7 | ||||
-rw-r--r-- | scene.cpp | 7 | ||||
-rw-r--r-- | shader.cpp | 4 | ||||
-rw-r--r-- | shader.h | 2 | ||||
-rw-r--r-- | shaders/terrain_fragment.glsl | 22 | ||||
-rw-r--r-- | shaders/terrain_vertex.glsl (renamed from terrain_vertex.glsl) | 7 | ||||
-rw-r--r-- | terrain_fragment.glsl | 11 |
8 files changed, 90 insertions, 58 deletions
@@ -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() { @@ -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); } @@ -92,3 +92,7 @@ void GLShaderProgram::use() { gl_check_error("Failed to use program"); } + +GLuint GLShaderProgram::get_program() { + return program; +} @@ -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: */ |