From 1b043477b605e9bbda11f9779ce8506a8686ac3c Mon Sep 17 00:00:00 2001 From: Mathias Gottschlag Date: Tue, 3 Mar 2009 20:24:21 +0100 Subject: [PATCH] Implemented Horde3D terrain textures. --- extra/horde3d/materials/light.material.xml | 3 + extra/horde3d/shaders/deferredLighting.shader | 103 +++++++++++++++ extra/horde3d/shaders/terrain.shader | 37 +++++- src/eal/horde3d/environment.cc | 35 +++++- src/eal/horde3d/environment.hh | 2 + src/eal/horde3d/extensions/island.cc | 174 ++++++++++++++++++++++++-- src/eal/horde3d/extensions/island.hh | 3 + 7 files changed, 338 insertions(+), 19 deletions(-) create mode 100644 extra/horde3d/materials/light.material.xml create mode 100644 extra/horde3d/shaders/deferredLighting.shader diff --git a/extra/horde3d/materials/light.material.xml b/extra/horde3d/materials/light.material.xml new file mode 100644 index 0000000..ca1940e --- /dev/null +++ b/extra/horde3d/materials/light.material.xml @@ -0,0 +1,3 @@ + + + diff --git a/extra/horde3d/shaders/deferredLighting.shader b/extra/horde3d/shaders/deferredLighting.shader new file mode 100644 index 0000000..458f4a7 --- /dev/null +++ b/extra/horde3d/shaders/deferredLighting.shader @@ -0,0 +1,103 @@ +[[FX]] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[[VS_QUAD]] + +varying vec2 texCoords; + +void main( void ) +{ + texCoords = gl_MultiTexCoord0.st; + gl_Position = gl_ProjectionMatrix * gl_Vertex; +} + + +[[FS_AMBIENT]] + +#include "shaders/utilityLib/fragDeferredRead.glsl" + +uniform samplerCube ambientMap; +varying vec2 texCoords; + +void main( void ) +{ + if( getMatID( texCoords ) == 0.0 ) // Background + { + gl_FragColor.rgb = vec3( 0, 0, 0 ); + } + else if( getMatID( texCoords ) == 2.0 ) // Sky + { + gl_FragColor.rgb = getAlbedo( texCoords ); + } + else + { + gl_FragColor.rgb = getAlbedo( texCoords ) * textureCube( ambientMap, getNormal( texCoords ) ).rgb; + } +} + + +[[FS_LIGHTING]] + +#include "shaders/utilityLib/fragLighting.glsl" +#include "shaders/utilityLib/fragDeferredRead.glsl" + +varying vec2 texCoords; + +void main( void ) +{ + if( getMatID( texCoords ) == 1.0 ) // Standard phong material + { + float vsPos = (gl_ModelViewMatrix * vec4( getPos( texCoords ), 1.0 )).z; + + gl_FragColor.rgb = + calcPhongSpotLight( getPos( texCoords ), getNormal( texCoords ), + getAlbedo( texCoords ), getSpecMask( texCoords ), 16.0, -vsPos, 0.3 ); + } + else discard; +} + + +[[FS_COPY_DEPTH]] + +uniform sampler2D depthBuf; +varying vec2 texCoords; + +void main( void ) +{ + gl_FragDepth = texture2D( depthBuf, texCoords ).r; +} diff --git a/extra/horde3d/shaders/terrain.shader b/extra/horde3d/shaders/terrain.shader index 83b9c1a..8e92870 100644 --- a/extra/horde3d/shaders/terrain.shader +++ b/extra/horde3d/shaders/terrain.shader @@ -9,6 +9,10 @@ + + + + @@ -34,18 +38,18 @@ uniform vec3 viewer; attribute vec2 texCoords0; -attribute vec3 normal; varying vec4 pos, vsPos; varying vec2 texCoords; varying vec3 tsbNormal; +uniform vec4 terrainSize; void main( void ) { // Calculate normal - vec3 _normal = calcWorldVec( normal ); + vec3 _normal = calcWorldVec( gl_Normal ); // Calculate tangent and bitangent tsbNormal = _normal; @@ -58,7 +62,7 @@ void main( void ) // Calculate tangent space eye vector // Calculate texture coordinates and clip space position - texCoords = vec2(pos.x, pos.z) / 64.0; + texCoords = vec2(gl_Vertex.x, gl_Vertex.z); gl_Position = gl_ModelViewProjectionMatrix * pos; } @@ -70,20 +74,27 @@ void main( void ) uniform vec4 specParams; uniform sampler2D colormap; +uniform sampler2D detailmap; varying vec4 pos; varying vec2 texCoords; varying vec3 tsbNormal; +uniform vec4 terrainSize; + void main( void ) { vec3 newCoords = vec3( texCoords, 0 ); // Flip texture vertically to match the GL coordinate system - newCoords.t *= -1.0; + //newCoords.t *= -1.0; + vec3 detail = texture2D( detailmap, newCoords.st ).rgb; + newCoords.s /= terrainSize.x; + newCoords.t /= terrainSize.y; vec3 albedo = texture2D( colormap, newCoords.st ).rgb; + albedo += (detail - 0.5) * 0.3; vec3 normal = tsbNormal; @@ -136,20 +147,27 @@ void main( void ) uniform vec4 specParams; uniform sampler2D colormap; +uniform sampler2D detailmap; varying vec4 pos, vsPos; varying vec2 texCoords; varying vec3 tsbNormal; +uniform vec4 terrainSize; + void main( void ) { vec3 newCoords = vec3( texCoords, 0 ); // Flip texture vertically to match the GL coordinate system - newCoords.t *= -1.0; + //newCoords.t *= -1.0; + vec3 detail = texture2D( detailmap, newCoords.st ).rgb; + newCoords.s /= terrainSize.x; + newCoords.t /= terrainSize.y; vec3 albedo = texture2D( colormap, newCoords.st ).rgb; + albedo += (detail - 0.5) * 0.3; vec3 normal = tsbNormal; @@ -166,6 +184,7 @@ void main( void ) #include "shaders/utilityLib/fragLighting.glsl" /> uniform sampler2D colormap; +uniform sampler2D detailmap; uniform samplerCube ambientMap; @@ -174,14 +193,20 @@ varying vec2 texCoords; varying vec3 tsbNormal; +uniform vec4 terrainSize; + void main( void ) { vec3 newCoords = vec3( texCoords, 0 ); // Flip texture vertically to match the GL coordinate system - newCoords.t *= -1.0; + //newCoords.t *= -1.0; + vec3 detail = texture2D( detailmap, newCoords.st ).rgb; + newCoords.s /= terrainSize.x; + newCoords.t /= terrainSize.y; vec3 albedo = texture2D( colormap, newCoords.st ).rgb; + albedo += (detail - 0.5) * 0.3; vec3 normal = tsbNormal; diff --git a/src/eal/horde3d/environment.cc b/src/eal/horde3d/environment.cc index 02b2e4c..ea6d8f9 100644 --- a/src/eal/horde3d/environment.cc +++ b/src/eal/horde3d/environment.cc @@ -26,6 +26,8 @@ #include #include +#include + namespace eal { Horde3DEnvironment::Horde3DEnvironment() @@ -86,7 +88,6 @@ namespace eal { currentdata[i] = heightdata[i]; } - printf("%d/%d\n", terrainsize + 1, terrainsize + 1); horde3d::Island::invalidate(terrain, 0, 0, terrainsize + 1, terrainsize + 1); } @@ -119,7 +120,14 @@ namespace eal } // Upload color data - + Horde3D::unloadResource(this->colormap); + if (!texturename) + this->colormap = Horde3D::createTexture2D("environment_colormap2", ResourceFlags::NoTexMipmaps, size, size, false); + else + this->colormap = Horde3D::createTexture2D("environment_colormap1", ResourceFlags::NoTexMipmaps, size, size, false); + texturename = 1 - texturename; + Horde3D::updateResourceData(this->colormap, TextureResParams::PixelData, colordata, size * size * 4); + Horde3D::setResourceParamItemi(material, MaterialResParams::Sampler, "colormap", this->colormap); delete[] colordata; } void Horde3DEnvironment::setColorMap (std::string path) @@ -146,15 +154,30 @@ namespace eal void Horde3DEnvironment::createTerrain() { - int material = Horde3D::addResource(ResourceTypes::Material, "materials/terrain.material.xml", 0 ); + material = Horde3D::addResource(ResourceTypes::Material, "materials/terrain.material.xml", 0 ); + ResHandle lightMatRes = Horde3D::addResource( ResourceTypes::Material, "materials/light.material.xml", 0 ); + ((Horde3DEngine*)Engine::get())->loadResources(); // Create terrain - int skybox = Horde3D::addResource(ResourceTypes::SceneGraph, "models/skybox/skybox.scene.xml", 0); + /*int skybox = Horde3D::addResource(ResourceTypes::SceneGraph, "models/skybox/skybox.scene.xml", 0); ((Horde3DEngine*)Engine::get())->loadResources(); - Horde3DUtils::loadResourcesFromDisk("media"); sky = Horde3D::addNodes(RootNode, skybox); - Horde3D::setNodeTransform(sky, 0, 0, 0, 0, 0, 0, 300, 300, 300); + Horde3D::setNodeTransform(sky, 0, 0, 0, 0, 0, 0, 300, 300, 300);*/ terrain = horde3d::Island::addIslandNode(RootNode, "terrain", terrainsize, terrainsize, material); Horde3D::setNodeTransform(terrain, -32 * terrainsize, -1600, -32 * terrainsize, 0, 0, 0, 64, 3200, 64); + colormap = Horde3D::createTexture2D("environment_colormap", ResourceFlags::NoTexMipmaps, 128, 128, false); + unsigned char texturedata[128 * 128 * 4]; + memset(texturedata, 128, 128 * 128 * 4); + Horde3D::updateResourceData(colormap, TextureResParams::PixelData, texturedata, 128 * 128 * 4); + Horde3D::setResourceParamItemi(material, MaterialResParams::Sampler, "colormap", colormap); + texturename = 0; + + NodeHandle light = Horde3D::addLightNode( RootNode, "Light1", lightMatRes, "LIGHTING", "" ); + Horde3D::setNodeTransform( light, 0, 300, 500, -90, 0, 0, 1, 1, 1 ); + Horde3D::setNodeParamf( light, LightNodeParams::Radius, 200 ); + Horde3D::setNodeParamf( light, LightNodeParams::FOV, 90 ); + Horde3D::setNodeParamf( light, LightNodeParams::Col_R, 0.9f ); + Horde3D::setNodeParamf( light, LightNodeParams::Col_G, 0.7f ); + Horde3D::setNodeParamf( light, LightNodeParams::Col_B, 0.75f ); } } diff --git a/src/eal/horde3d/environment.hh b/src/eal/horde3d/environment.hh index 3483b71..6f86a1e 100644 --- a/src/eal/horde3d/environment.hh +++ b/src/eal/horde3d/environment.hh @@ -70,6 +70,8 @@ namespace eal int terrain; int terrainsize; int colormap; + int material; + int texturename; int sky; int water; diff --git a/src/eal/horde3d/extensions/island.cc b/src/eal/horde3d/extensions/island.cc index 5c8c287..0a19483 100644 --- a/src/eal/horde3d/extensions/island.cc +++ b/src/eal/horde3d/extensions/island.cc @@ -86,6 +86,8 @@ namespace eal Modules::renderer().setShader(&debugViewShader); } + int terrainSize = glGetUniformLocation( Modules::renderer().getCurShader()->shaderObject, "terrainSize" ); + Vec3f localCamPos( curCam->getAbsTrans().x[12], curCam->getAbsTrans().x[13], curCam->getAbsTrans().x[14] ); localCamPos = island->_absTrans.inverted() * localCamPos; // Draw terrain @@ -117,6 +119,9 @@ namespace eal glUniformMatrix3fv(curShader->uni_worldNormalMat, 1, false, normalMat ); } + if( terrainSize >= 0 ) + glUniform4f( terrainSize, island->sizeX, island->sizeZ, 0, 0 ); + glDrawElements(GL_TRIANGLES, TILE_SIZE * TILE_SIZE * 6, GL_UNSIGNED_SHORT, (char *)0); Modules::renderer().incStat(EngineStats::BatchCount, 1); Modules::renderer().incStat(EngineStats::TriCount, TILE_SIZE * TILE_SIZE * 2); @@ -218,8 +223,8 @@ namespace eal meshQuality(islandTpl.meshQuality), heightdata(islandTpl.heightdata) { _renderable = true; - localBBox.getMinCoords() = Vec3f(-1000, 0, -1000); - localBBox.getMaxCoords() = Vec3f(1000, 1, 1000); + localBBox.getMinCoords() = Vec3f(-1000, -1000, -1000); + localBBox.getMaxCoords() = Vec3f(1000, 1000, 1000); for (int i = 0; i < TILE_COUNT; i++) { terrainpatches[i] = 0; @@ -320,9 +325,10 @@ namespace eal { int tilesx = sizeX / TILE_SIZE; int tilesz = sizeZ / TILE_SIZE; + int size = (TILE_SIZE + 1) * (TILE_SIZE + 1) * 3; // Set vertex data // TODO: Optimize this - for (int iz = 0; iz < height; iz++) + /*for (int iz = 0; iz < height; iz++) { int tilez = (iz + y) / TILE_SIZE; int offsetz = (iz + y) % TILE_SIZE; @@ -374,30 +380,54 @@ namespace eal } } } + }*/ + for (int iz = 0; iz < height; iz++) + { + for (int ix = 0; ix < width; ix ++) + { + setHeight(x + ix, y + iz, heightdata[(iz + y) * (sizeX + 1) + (ix + x)]); + } } // Compute normals for (int iz = 0; iz < height; iz++) { + int tilez = (iz + y) / TILE_SIZE; + int offsetz = (iz + y) % TILE_SIZE; + if (tilez == tilesz) + { + tilez--; + offsetz = TILE_SIZE; + } for (int ix = 0; ix < width; ix ++) { + int tilex = (ix + x) / TILE_SIZE; + int offsetx = (ix + x) % TILE_SIZE; + if (tilex == tilesx) + { + tilex--; + offsetx = TILE_SIZE; + } float h1 = getHeight(x + ix - 1, y + iz); float h2 = getHeight(x + ix + 1, y + iz); float h3 = getHeight(x + ix, y + iz - 1); float h4 = getHeight(x + ix, y + iz + 1); Vec3f v1(2.0f, h2 - h1, 0.0f); Vec3f v2(0.0f, h4 - h3, 2.0f); - Vec3f normal = v1.cross(v2); + Vec3f normal = v2.cross(v1).normalized(); + /*float *vertex = &vertexdata[tilex + tilez * EDGE_TILES][(offsetz * (TILE_SIZE + 1) + offsetx) * 3 + size]; + vertex[0] = normal.x; + vertex[1] = normal.y; + vertex[2] = normal.z;*/ + updateNormal(x + ix, y + iz); } } // Refresh vertex buffers - int size = (TILE_SIZE + 1) * (TILE_SIZE + 1) * 3; for (int iz = y / TILE_SIZE; iz <= (y + height) / TILE_SIZE; iz++) { for (int ix = x / TILE_SIZE; ix <= (x + width) / TILE_SIZE; ix++) { - printf("Updating.\n"); Modules::renderer().updateVertices(vertexdata[ix + iz * EDGE_TILES], - 0, size * sizeof(float), terrainpatches[ix + iz * EDGE_TILES]); + 0, size * sizeof(float) * 2, terrainpatches[ix + iz * EDGE_TILES]); } } } @@ -411,5 +441,135 @@ namespace eal { return heightdata; } + + void IslandNode::setHeight(int x, int z, float height) + { + int tilesx = sizeX / TILE_SIZE; + int tilesz = sizeZ / TILE_SIZE; + int size = (TILE_SIZE + 1) * (TILE_SIZE + 1) * 3; + // Set vertex data + // TODO: Optimize this + int tilez = z / TILE_SIZE; + int offsetz = z % TILE_SIZE; + if (tilez == tilesz) + { + tilez--; + offsetz = TILE_SIZE; + } + { + int tilex = x / TILE_SIZE; + int offsetx = x % TILE_SIZE; + if (tilex == tilesx) + { + tilex--; + offsetx = TILE_SIZE; + } + float *vertex = &vertexdata[tilex + tilez * EDGE_TILES][(offsetz * (TILE_SIZE + 1) + offsetx) * 3]; + vertex[1] = height; + if ((offsetx == 0) && (tilex > 0)) + { + tilex--; + offsetx = TILE_SIZE; + float *vertex = &vertexdata[tilex + tilez * EDGE_TILES][(offsetz * (TILE_SIZE + 1) + offsetx) * 3]; + vertex[1] = height; + } + } + if ((offsetz == 0) && (tilez > 0)) + { + tilez--; + offsetz = TILE_SIZE; + { + int tilex = x / TILE_SIZE; + int offsetx = x % TILE_SIZE; + if (tilex == tilesx) + { + tilex--; + offsetx = TILE_SIZE; + } + float *vertex = &vertexdata[tilex + tilez * EDGE_TILES][(offsetz * (TILE_SIZE + 1) + offsetx) * 3]; + vertex[1] = height; + if ((offsetx == 0) && (tilex > 0)) + { + tilex--; + offsetx = TILE_SIZE; + float *vertex = &vertexdata[tilex + tilez * EDGE_TILES][(offsetz * (TILE_SIZE + 1) + offsetx) * 3]; + vertex[1] = height; + } + } + } + } + void IslandNode::updateNormal(int x, int z) + { + // Compute normal + float h1 = getHeight(x - 1, z); + float h2 = getHeight(x + 1, z); + float h3 = getHeight(x, z - 1); + float h4 = getHeight(x, z + 1); + Vec3f v1(2.0f, h2 - h1, 0.0f); + Vec3f v2(0.0f, h4 - h3, 2.0f); + Vec3f normal = v2.cross(v1).normalized(); + + int tilesx = sizeX / TILE_SIZE; + int tilesz = sizeZ / TILE_SIZE; + int size = (TILE_SIZE + 1) * (TILE_SIZE + 1) * 3; + // Set vertex data + // TODO: Optimize this + int tilez = z / TILE_SIZE; + int offsetz = z % TILE_SIZE; + if (tilez == tilesz) + { + tilez--; + offsetz = TILE_SIZE; + } + { + int tilex = x / TILE_SIZE; + int offsetx = x % TILE_SIZE; + if (tilex == tilesx) + { + tilex--; + offsetx = TILE_SIZE; + } + float *vertex = &vertexdata[tilex + tilez * EDGE_TILES][(offsetz * (TILE_SIZE + 1) + offsetx) * 3 + size]; + vertex[0] = normal.x; + vertex[1] = normal.y; + vertex[2] = normal.z; + if ((offsetx == 0) && (tilex > 0)) + { + tilex--; + offsetx = TILE_SIZE; + float *vertex = &vertexdata[tilex + tilez * EDGE_TILES][(offsetz * (TILE_SIZE + 1) + offsetx) * 3 + size]; + vertex[0] = normal.x; + vertex[1] = normal.y; + vertex[2] = normal.z; + } + } + if ((offsetz == 0) && (tilez > 0)) + { + tilez--; + offsetz = TILE_SIZE; + { + int tilex = x / TILE_SIZE; + int offsetx = x % TILE_SIZE; + if (tilex == tilesx) + { + tilex--; + offsetx = TILE_SIZE; + } + float *vertex = &vertexdata[tilex + tilez * EDGE_TILES][(offsetz * (TILE_SIZE + 1) + offsetx) * 3 + size]; + vertex[0] = normal.x; + vertex[1] = normal.y; + vertex[2] = normal.z; + if ((offsetx == 0) && (tilex > 0)) + { + tilex--; + offsetx = TILE_SIZE; + float *vertex = &vertexdata[tilex + tilez * EDGE_TILES][(offsetz * (TILE_SIZE + 1) + offsetx) * 3 + size]; + vertex[0] = normal.x; + vertex[1] = normal.y; + vertex[2] = normal.z; + } + } + } + } } } diff --git a/src/eal/horde3d/extensions/island.hh b/src/eal/horde3d/extensions/island.hh index 5ce1673..24e1158 100644 --- a/src/eal/horde3d/extensions/island.hh +++ b/src/eal/horde3d/extensions/island.hh @@ -98,6 +98,9 @@ namespace eal void createVertexBuffers(); void createExtension(); + void setHeight(int x, int z, float height); + void updateNormal(int x, int z); + PMaterialResource materialRes; int sizeX; int sizeZ; -- 2.11.4.GIT