Ver Fonte

Added Terrain test to gameplay-tests app (still a couple features to add to it).
Couple minor fixes to Terrain.
Updated gameplay-encoder to support object-space normal map generation from RAW8 and RAW16 files.
Added script camera to gameplay-tests.

sgrenier há 13 anos atrás
pai
commit
f20052fb65

+ 72 - 11
gameplay-encoder/src/NormalMapGenerator.cpp

@@ -60,6 +60,16 @@ void calculateNormal(
     Vector3::cross(Q, P, normal);
 }
 
+float normalizedHeightPacked(float r, float g, float b)
+{
+    // This formula is intended for 24-bit packed heightmap images (that are generated
+    // with gameplay-encoder. However, it is also compatible with normal grayscale 
+    // heightmap images, with an error of approximately 0.4%. This can be seen by
+    // setting r=g=b=x and comparing the grayscale height expression to the packed
+    // height expression: the error is 2^-8 + 2^-16 which is just under 0.4%.
+    return (256.0f*r + g + 0.00390625f*b) / 65536.0f;
+}
+
 void NormalMapGenerator::generate()
 {
     // Load the input heightmap
@@ -76,8 +86,6 @@ void NormalMapGenerator::generate()
             return;
         }
 
-        // TODO: Add command-line argument for high precision heightmaps
-
         _resolutionX = image->getWidth();
         _resolutionY = image->getHeight();
         int size = _resolutionX * _resolutionY;
@@ -88,20 +96,20 @@ void NormalMapGenerator::generate()
             switch (image->getFormat())
             {
             case Image::LUMINANCE:
-                heights[i] = data[i];
+                heights[i] = data[i] / 255.0f;
                 break;
             case Image::RGB:
             case Image::RGBA:
                 {
                     int pos = i * image->getBpp();
-                    heights[i] = (data[pos] + data[pos+1] + data[pos+2]) / 3.0f;
+                    heights[i] = normalizedHeightPacked(data[pos], data[pos+1], data[pos+2]);
                 }
                 break;
             default:
                 heights[i] = 0.0f;
                 break;
             }
-            heights[i] = (heights[i] / 255.0f) * _worldSize.y;
+            heights[i] = heights[i] * _worldSize.y;
         }
         SAFE_DELETE(image);
     }
@@ -110,16 +118,69 @@ void NormalMapGenerator::generate()
         // Load heights from RAW 8 or 16-bit file
         if (_resolutionX <= 0 || _resolutionY <= 0)
         {
-            LOG(1, "Missing resolution argument - must be explicitly specified for RAW heightmap files: %s\n.", _inputFile.c_str());
+            LOG(1, "Missing resolution argument - must be explicitly specified for RAW heightmap files: %s.\n", _inputFile.c_str());
             return;
         }
 
-        // TODO
-        heights = new float[_resolutionX * _resolutionY];
-        // TODO
+        // Read all data from file
+        FILE* fp = fopen(_inputFile.c_str(), "rb");
+        if (fp == NULL)
+        {
+            LOG(1, "Failed to open input file: %s.\n", _inputFile.c_str());
+            return;
+        }
 
-        LOG(1, "RAW files not yet implemented...");
-        return;
+        fseek(fp, 0, SEEK_END);
+        long fileSize = ftell(fp);
+        fseek(fp, 0, SEEK_SET);
+
+        unsigned char* data = new unsigned char[fileSize];
+        if (fread(data, 1, fileSize, fp) != fileSize)
+        {
+            fclose(fp);
+            delete[] data;
+            LOG(1, "Failed to read bytes from input file: %s.\n", _inputFile.c_str());
+            return;
+        }
+        fclose(fp);
+
+        // Determine if the RAW file is 8-bit or 16-bit based on file size.
+        int bits = (fileSize / (_resolutionX * _resolutionY)) * 8;
+        if (bits != 8 && bits != 16)
+        {
+            LOG(1, "Invalid RAW file - must be 8-bit or 16-bit, but found neither: %s.", _inputFile.c_str());
+            delete[] data;
+            return;
+        }
+
+        int size = _resolutionX * _resolutionY;
+        heights = new float[size];
+        if (bits == 16)
+        {
+            // 16-bit (0-65535)
+            int idx;
+            for (unsigned int y = 0, i = 0; y < _resolutionY; ++y)
+            {
+                for (unsigned int x = 0; x < _resolutionX; ++x, ++i)
+                {
+                    idx = (y * _resolutionX + x) << 1;
+                    heights[i] = ((data[idx] | (int)data[idx+1] << 8) / 65535.0f) * _worldSize.y;
+                }
+            }
+        }
+        else
+        {
+            // 8-bit (0-255)
+            for (unsigned int y = 0, i = 0; y < _resolutionY; ++y)
+            {
+                for (unsigned int x = 0; x < _resolutionX; ++x, ++i)
+                {
+                    heights[i] = (data[y * _resolutionX + x] / 255.0f) * _worldSize.y;
+                }
+            }
+        }
+
+        delete[] data;
     }
     else
     {

+ 2 - 1
gameplay/res/shaders/terrain.frag

@@ -47,7 +47,8 @@ void main()
 #if (LAYER_COUNT > 0)
     // Set base diffuse color
     vec2 uvCoord = mod(v_texCoord0 * TEXTURE_REPEAT_0, vec2(1,1));
-	_baseColor = texture2D(u_samplers[TEXTURE_INDEX_0], uvCoord);
+	_baseColor.rgb = texture2D(u_samplers[TEXTURE_INDEX_0], uvCoord).rgb;
+    _baseColor.a = 1;
 #else
     // If no layers are defined, simple use a white color
     _baseColor = vec4(1,1,1,1);

+ 2 - 4
gameplay/src/TerrainPatch.cpp

@@ -488,11 +488,9 @@ bool TerrainPatch::updateMaterial()
         material->getParameter("u_lightColor")->bindValue(this, &TerrainPatch::getLightColor);
         material->getParameter("u_lightDirection")->bindValue(this, &TerrainPatch::getLightDirection);
         if (_layers.size() > 0)
-        {
             material->getParameter("u_samplers")->setValue((const Texture::Sampler**)&_samplers[0], (unsigned int)_samplers.size());
-            if (_terrain->_normalMap)
-                material->getParameter("u_normalMap")->setValue(_terrain->_normalMap);
-        }
+        if (_terrain->_normalMap)
+            material->getParameter("u_normalMap")->setValue(_terrain->_normalMap);
 
         if (_terrain->isFlagSet(Terrain::DEBUG_PATCHES))
         {