Volumes Of Fun
http://www.volumesoffun.com/phpBB3/

[Solved] Materials and Ogre
http://www.volumesoffun.com/phpBB3/viewtopic.php?f=14&t=203
Page 1 of 2

Author:  Will Smith [ Sat Apr 23, 2011 1:03 pm ]
Post subject:  [Solved] Materials and Ogre

Update: Switched from using shaders to assigning uvs when building the manual object. Below has the solution.

Author:  David Williams [ Sat Apr 23, 2011 6:31 pm ]
Post subject:  Re: Help with Shader Materials and Ogre

My guess would be that the problem is in your shader code rather than the C++ code. Have you got it working correctly if you apply a single texture rather than trying to pick out part of a texture atlas? If not you need to start there. Then bring in the texture atlas code but on a texture atlas with only 1 texture. Then a texture atlas with two textures, etc. Build it up slowly.

Also, in your vertex shader you are doing direct comparisons with floating point values ( != 0.0). This is generally bad practice due to floating point inaccuracies.

Author:  Shanee [ Sun Apr 24, 2011 7:40 am ]
Post subject:  Re: Help with Shader Materials and Ogre

Try to see into my latest post and decided if texture atlases actually worth it, although for cubic terrain I guess there is no real use for my method as there shouldn't be problems with wrapping/mipmaps/blending(?)

viewtopic.php?p=1642#p1642

Author:  Will Smith [ Sun Apr 24, 2011 8:26 am ]
Post subject:  Re: Help with Shader Materials and Ogre

Interesting approach, I by no means need a texture atlas, i'm just trying to get any form of per voxel textures working.

Author:  David Williams [ Sun Apr 24, 2011 8:44 am ]
Post subject:  Re: Help with Shader Materials and Ogre

If you only have a small number of textures, you can also pass them in as different texture units (using texture_unit in your material script) because a shader can have a number of different textures bound simultaneously. You can then pick which texture to sample based on your material.

Author:  Shanee [ Sun Apr 24, 2011 9:01 am ]
Post subject:  Re: Help with Shader Materials and Ogre

David Williams wrote:
If you only have a small number of textures, you can also pass them in as different texture units (using texture_unit in your material script) because a shader can have a number of different textures bound simultaneously. You can then pick which texture to sample based on your material.


Which leads to branching in pixel shader which is quite slow :) Try to read my post, I think we should compare the techniques sometime and figure what might be most recommended technique.

In my technique I described in the post multiple texture slots is used only for triangles which require multiple materials for blending, other than that every uniform triangles are drawn without more than one texture sample.

Then again the drawback is additional batching (draw calls) which I explained my preference for quite a bit in the post.

Author:  David Williams [ Sun Apr 24, 2011 9:11 am ]
Post subject:  Re: Help with Shader Materials and Ogre

Shanee wrote:
Which leads to branching in pixel shader which is quite slow :)

Probably, but the point is he just needs to get something working first. Using separate texture units is probably simpler than using texture arrays.

Author:  Shanee [ Sun Apr 24, 2011 10:04 am ]
Post subject:  Re: Help with Shader Materials and Ogre

Depends what you mean, multiple texture units sure is more simple than texture atlas or texture array, but I wasn't recommending those :)

The question is Texture Splatting vs Separating the mesh. And I'd say Texture Splatting is indeed simplier and requires less code than what I presented.

Author:  Will Smith [ Sun Aug 28, 2011 9:29 pm ]
Post subject:  Re: Help with Shader Materials and Ogre

I've recently come back to this project of mine, and I my goal is to not use shaders at all.
I have textures working but 2 faces of the 4 sides on a cube have their uv's rotated 90degrees :{

The arrows should all be pointing UP
Image

I'm sure it's something simple but I'm not sure where I am going wrong. Here is how i create the manual object and assign UV's.

Code:
//Create ManualObject from SurfaceMesh
void VoxelManager::SurfaceMeshToRender(const PolyVox::SurfaceMesh<PositionMaterialNormal>&mesh, Ogre::ManualObject* manual, std::string materialName, bool isUpdate)
{   
   //Are we using a cg shader?
   bool isTextureShader = false;
   
   const std::vector<uint32_t>& vecIndices = mesh.getIndices();
   const std::vector<PositionMaterialNormal>& vecVertices = mesh.getVertices();
   
   if(vecVertices.size() < 1)
   {
         return;   
   }
   
   //Build the Ogre Manual Object.
   if(isUpdate)
   {
      manual->beginUpdate(0);
   }
   else
   {
      manual->begin(materialName, Ogre::RenderOperation::OT_TRIANGLE_LIST);
   }

   // Used only if not using Shader
   const Ogre::Vector2 texCoords[4] =   { Ogre::Vector2(0.0f, 1.0f), Ogre::Vector2(1.0f, 1.0f), Ogre::Vector2(0.0f, 0.0f), Ogre::Vector2(1.0f, 0.0f) };   
   size_t texIdx = 0;
   
   for (vector<PositionMaterialNormal>::const_iterator itVertex = vecVertices.begin(); itVertex != vecVertices.end(); ++itVertex)
   {
      //Shader
      if(isTextureShader)
      {
         Vector3DFloat pos = itVertex->getPosition();
         manual->position(pos.getX(), pos.getY(), pos.getZ());
      }
      else
      {
         const PositionMaterialNormal& vertex = *itVertex;
         const Vector3DFloat& vertPos = vertex.getPosition();         

         manual->position(vertPos.getX(), vertPos.getY(), vertPos.getZ());
         manual->normal(vertex.getNormal().getX(), vertex.getNormal().getY(), vertex.getNormal().getZ());

         manual->textureCoord(texCoords[texIdx % 4]);
         texIdx++;         
         
      }
   }
   
   //Then iterate through the indices add create the indices list.
   for (vector<uint32_t>::const_iterator itIdx = vecIndices.begin(); itIdx != vecIndices.end(); ++itIdx)
   {
      manual->index(*itIdx);
   }
   
   manual->end();   
}




I'm sorry for asking to be spoonfed a solution, but I don't have a very good understanding of constructing primitives based on vertex data. I assumed each face was constructed in the same order of 4 points, so I don't understand why half the faces are rotated.

If I manage to figure it out, I'll post it so other people can see the solution.

Author:  David Williams [ Mon Aug 29, 2011 10:34 am ]
Post subject:  Re: Help with Shader Materials and Ogre

Will Smith wrote:
I'm sorry for asking to be spoonfed a solution, but I don't have a very good understanding of constructing primitives based on vertex data. I assumed each face was constructed in the same order of 4 points, so I don't understand why half the faces are rotated.


This is an interesting question. There's no problem with your code, it's actually the triangles generated by PolyVox which are in an inconsistant order.

Off the top of my head I couldn't tell you what order the vertices are in, and I didn't give it much thought when writing the code, for the simple reason that it's not possible to get all three axis to line up. Think of it like this, even if the arrows on your walls did line up, what would happen if you also drew arrows on the floor? Because your walls are at 90 degrees to each other, the arrows on the floor would not be able to line up with both sets of walls. The best you could do would be to have the arrows on the floor line up with one set of walls.

What I'm really saying is that in the general case there is no 'correct' way to assign the texture coordinates, which is part of the reason PolyVox does not provide texture coordinates. However, your case is more specific than the general case - you know that two of your axes represent walls and the that the textures on these should be aligned, and the the other axis represents floor/ceiling and the alignment here doesn't matter.

Hopefully that justifies why it behaves in the current way. The good news is it shouldn't be hard for you to get the behaviour you want - you simply need to consider each of the six faces seperaty based on the normal. This code is untested but should give you the idea:

Code:
else
{
   const PositionMaterialNormal& vertex = *itVertex;
   const Vector3DFloat& vertPos = vertex.getPosition();

   manual->position(vertPos.getX(), vertPos.getY(), vertPos.getZ());
   manual->normal(vertex.getNormal().getX(), vertex.getNormal().getY(), vertex.getNormal().getZ());

   if(vertex.getNormal().getX() > 0.5f) //Face points along positive X
   {
      manual->textureCoord(texCoordsForPositiveX[texIdx % 4]);
   }
   else if(vertex.getNormal().getX() < -0.5f) //Face points along negative X
   {
      manual->textureCoord(texCoordsForNegativeX[texIdx % 4]);
   }
   else if(vertex.getNormal().getY() > 0.5f) //Face points along positive Y
   {
      manual->textureCoord(texCoordsForPositivey[texIdx % 4]);
   }
   else if(vertex.getNormal().getY() < -0.5f) //Face points along negative Y
   {
      manual->textureCoord(texCoordsForNegativeY[texIdx % 4]);
   }
   else if(vertex.getNormal().getZ() > 0.5f) //Face points along positive Z
   {
      manual->textureCoord(texCoordsForPositiveZ[texIdx % 4]);
   }
   else if(vertex.getNormal().getZ() < -0.5f) //Face points along negative Z
   {
      manual->textureCoord(texCoordsForNegativeZ[texIdx % 4]);
   }
   texIdx++;
}


Note that I've replaced your 'texCoords' array with six new arrays - one for each face ('texCoordsForPositiveX', etc). Start of with each off these the same as your original texCoords array, and the tweak the values for each face until you are happy.

Let us know how that works out. There may be a better way as I haven't given much thought to doing this on the CPU rather than in shaders, so feel free to experiment.

Page 1 of 2 All times are UTC
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/