Ogre Version: : 13 6 5
Operating System: :Linux Tumbleweed:
Render System: :OpenGL3+
Hello, what I try is the manual, procedural resource creation. I want a texture be generated from shader programs , to do that I created ORTHO camera, and mesh quad which is supposed to do :
Code: Select all
" // Create the render texture
perlinTexture = Ogre::TextureManager::getSingleton().createManual(
"PerlinNoiseTexture",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D,
4096, 4096,
0,
Ogre::PF_R8G8B8A8,
Ogre::TU_RENDERTARGET
);
// Attach a camera and viewport to render the texture
Ogre::RenderTexture* renderTexture = perlinTexture->getBuffer()->getRenderTarget();
Ogre::Camera* camera = sceneManager->createCamera("PerlinNoiseCam");
camera->setProjectionType(Ogre::PT_ORTHOGRAPHIC);
camera->setOrthoWindow(4096, 4096);
getRenderWindow()->addViewport(camera);
Ogre::Viewport* viewport = renderTexture->addViewport(camera);
viewport->setClearEveryFrame(true);
viewport->setBackgroundColour(Ogre::ColourValue::Blue);
viewport->setOverlaysEnabled(false);
// Create a quad
Ogre::Plane plane(Ogre::Vector3::UNIT_Z, 0);
Ogre::MeshManager::getSingleton().createPlane(
"Plane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
plane, 4096, 4096, 1, 1, true, 1, 1, 1, Ogre::Vector3::UNIT_Y);
Ogre::Entity* quadEntity = sceneManager->createEntity("Plane");
quadEntity->setMaterialName("Cloud", "General");
Ogre::SceneNode* quadNode = sceneManager->getRootSceneNode()->createChildSceneNode();
quadNode->attachObject(quadEntity);
quadNode->setPosition(0, 0, -1000);
sceneManager->setAmbientLight(Ogre::ColourValue(.5, .5, .5));
Ogre::LogManager::getSingleton().logMessage("Setup complete.");"
The main question here is why I cannot use the perlinTexture as a base for my material with a new Entity ?
It's not the fault of assigning the material with texture. cause the program works perfectly well for custom texture ( for example a genreated red one ... )
I have even tried to copy over the contents to a new texture -- freshTexture without success , it always crashes somewhere on rendering within the SceneManager code. Maybe the culprit is I try to use two OgreBites applications ? Please have a look at whole code here :
Code: Select all
#include <Ogre.h>
#include <OgreShaderGenerator.h>
#include <OgreApplicationContext.h>
#include <iostream>
Ogre::TexturePtr perlinTexture;
void setupTileMesh(Ogre::SceneManager* sceneMgr, const Ogre::String& meshName, Ogre::TexturePtr myTexture)
{
// Bind the PerlinNoiseTexture to the CloudMaterial programmatically
Ogre::MaterialPtr cloudMaterial = Ogre::MaterialManager::getSingleton().getByName("Fog");
if (!cloudMaterial.isNull())
{
Ogre::Pass* pass = cloudMaterial->getTechnique(0)->getPass(0);
Ogre::TextureUnitState* texState = pass->getTextureUnitState(0);
if (texState != nullptr && !myTexture.isNull())
{
texState->setTexture(myTexture);
}
else
{
std::cerr << "Error: TextureUnitState or myTexture is null." << std::endl;
return;
}
// Assuming the meshName points to a pre-loaded mesh
Ogre::Entity* tileEntity = sceneMgr->createEntity(meshName);
Ogre::SceneNode* tileNode = sceneMgr->getRootSceneNode()->createChildSceneNode();
// Check and apply materials to submeshes
if (tileEntity->getNumSubEntities() > 1)
{
// Apply DirtMaterial to the first submesh
tileEntity->getSubEntity(0)->setMaterialName("Dirt");
// Apply CloudMaterial to the second submesh
tileEntity->getSubEntity(1)->setMaterial(cloudMaterial);
// Apply CloudMaterial to the third submesh
tileEntity->getSubEntity(2)->setMaterial(cloudMaterial);
// Debugging output to check submesh count
std::cout << "Submesh count: " << tileEntity->getNumSubEntities() << std::endl;
}
else
{
std::cerr << "Error: Not enough submeshes in the entity." << std::endl;
return;
}
tileNode->attachObject(tileEntity);
}
else
{
std::cerr << "Error: Cloud material 'Fog' is null." << std::endl;
}
}
// Function to save PerlinNoiseTexture to an image file
void savePerlinNoiseTexture(Ogre::TexturePtr texture, const std::string& filename) {
Ogre::HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer();
Ogre::Image image;
pixelBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY);
const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
image.loadDynamicImage(static_cast<Ogre::uchar*>(pixelBox.data), texture->getWidth(), texture->getHeight(),
1, texture->getFormat(), true);
image.save(filename);
pixelBuffer->unlock();
}
class MyApplication : public OgreBites::ApplicationContext, public OgreBites::InputListener {
public:
MyApplication() : OgreBites::ApplicationContext("MyApplication") {}
void setup() {
OgreBites::ApplicationContext::setup();
addInputListener(this);
Ogre::Root* root = getRoot();
Ogre::SceneManager* sceneManager = root->createSceneManager("OctreeSceneManager", "SceneManager");
// Load resources
Ogre::ConfigFile cf;
cf.load("resources.cfg");
Ogre::String name, locType;
Ogre::ConfigFile::SectionIterator secIt = cf.getSectionIterator();
while (secIt.hasMoreElements()) {
Ogre::ConfigFile::SettingsMultiMap* settings = secIt.getNext();
for (auto& pair : *settings) {
locType = pair.first;
name = pair.second;
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(name, locType);
}
}
// Create the render texture
perlinTexture = Ogre::TextureManager::getSingleton().createManual(
"PerlinNoiseTexture",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D,
4096, 4096,
0,
Ogre::PF_R8G8B8A8,
Ogre::TU_RENDERTARGET
);
// Attach a camera and viewport to render the texture
Ogre::RenderTexture* renderTexture = perlinTexture->getBuffer()->getRenderTarget();
Ogre::Camera* camera = sceneManager->createCamera("PerlinNoiseCam");
camera->setProjectionType(Ogre::PT_ORTHOGRAPHIC);
camera->setOrthoWindow(4096, 4096);
getRenderWindow()->addViewport(camera);
Ogre::Viewport* viewport = renderTexture->addViewport(camera);
viewport->setClearEveryFrame(true);
viewport->setBackgroundColour(Ogre::ColourValue::Blue);
viewport->setOverlaysEnabled(false);
// Create a quad
Ogre::Plane plane(Ogre::Vector3::UNIT_Z, 0);
Ogre::MeshManager::getSingleton().createPlane(
"Plane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
plane, 4096, 4096, 1, 1, true, 1, 1, 1, Ogre::Vector3::UNIT_Y);
Ogre::Entity* quadEntity = sceneManager->createEntity("Plane");
quadEntity->setMaterialName("Cloud", "General");
Ogre::SceneNode* quadNode = sceneManager->getRootSceneNode()->createChildSceneNode();
quadNode->attachObject(quadEntity);
quadNode->setPosition(0, 0, -1000);
sceneManager->setAmbientLight(Ogre::ColourValue(.5, .5, .5));
Ogre::LogManager::getSingleton().logMessage("Setup complete.");
}
};
class MyApplication2 : public OgreBites::ApplicationContext, public OgreBites::InputListener {
public:
MyApplication2() : OgreBites::ApplicationContext("MyApplication2") {}
void setup()
{
// Call the base class setup
OgreBites::ApplicationContext::setup();
// Load resources
Ogre::ConfigFile cf;
cf.load("resources.cfg");
Ogre::String name, locType;
Ogre::ConfigFile::SectionIterator secIt = cf.getSectionIterator();
while (secIt.hasMoreElements()) {
Ogre::ConfigFile::SettingsMultiMap* settings = secIt.getNext();
for (auto& pair : *settings) {
locType = pair.first;
name = pair.second;
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(name, locType);
}
}
// Register as an input listener
addInputListener(this);
// Get the root, render window, and scene manager
Ogre::Root* root = getRoot();
Ogre::RenderWindow* window = getRenderWindow();
Ogre::SceneManager* scnMgr = root->createSceneManager("OctreeSceneManager","SceneManager2");
// Set up camera
Ogre::Camera* cam = scnMgr->createCamera("MainCamera");
cam->setAutoAspectRatio(true);
cam->setNearClipDistance(5);
// Create a viewport
Ogre::Viewport* vp = window->addViewport(cam);
vp->setBackgroundColour(Ogre::ColourValue(0, 0, 0));
cam->setAspectRatio(Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight()));
// Set up a scene
Ogre::SceneNode* rootNode = scnMgr->getRootSceneNode();
Ogre::SceneNode* camNode = rootNode->createChildSceneNode();
camNode->setPosition(Ogre::Vector3(5,5,5));
camNode->attachObject(cam);
camNode->lookAt(Ogre::Vector3(0,0,0), Ogre::Node::TS_WORLD);
scnMgr->setAmbientLight(Ogre::ColourValue(.5, .5, .5));
Ogre::Light* light = scnMgr->createLight("MainLight");
Ogre::SceneNode* lightNode = rootNode->createChildSceneNode();
lightNode->setPosition(2, 8, 5);
lightNode->attachObject(light);
}
};
Ogre::TexturePtr createRedTexture(Ogre::String textureName, int width, int height)
{
// Create a manual texture
Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().createManual(
textureName,
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D,
width, height,
0,
Ogre::PF_R8G8B8A8,
Ogre::TU_DEFAULT
);
if (texture.isNull())
{
std::cerr << "Error: Texture creation failed." << std::endl;
return Ogre::TexturePtr();
}
// Lock the texture buffer to fill it with red color
Ogre::HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer();
pixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
uint8_t* pDest = static_cast<uint8_t*>(pixelBox.data);
// Fill the texture with red color
for (size_t y = 0; y < height; ++y)
{
for (size_t x = 0; x < width; ++x)
{
size_t pixelIndex = (y * width + x) * 4;
pDest[pixelIndex] = 255; // Red
pDest[pixelIndex + 1] = 0; // Green
pDest[pixelIndex + 2] = 0; // Blue
pDest[pixelIndex + 3] = 255; // Alpha
}
}
// Unlock the buffer to apply changes
pixelBuffer->unlock();
return texture;
}
int main(int argc, char** argv) {
Ogre::TexturePtr freshTexture;
// Prepare a PixelBox for copying the content
Ogre::PixelBox srcPixelBox(
Ogre::Box(0, 0, 4096, 4096),
Ogre::PF_R8G8B8A8,
new uint8_t[4096 * 4096 * 4] // Allocate memory for the pixel data
);
// Cleanup the allocated memory for the PixelBoxes
try
{
MyApplication app;
app.initApp();
// Render multiple frames to ensure the texture is correctly updated
app.getRoot()->startRendering();
// Create a fresh texture to copy the content
freshTexture = Ogre::TextureManager::getSingleton().createManual(
"FreshPerlinTexture",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D,
4096, 4096,
0,
Ogre::PF_R8G8B8A8,
Ogre::TU_DEFAULT
);
// Copy the content from perlinTexture to the source PixelBox
perlinTexture->getBuffer()->blitToMemory(srcPixelBox);
// Copy the content from the source PixelBox to the destination PixelBox
freshTexture->getBuffer()->blitFromMemory(srcPixelBox);
delete[] static_cast<uint8_t*>(srcPixelBox.data);
app.closeApp();
}
catch (const Ogre::Exception& e) {
std::cerr << "An exception has occurred: " << e.getFullDescription().c_str() << std::endl;
return 1;
}
MyApplication2 app2;
app2.initApp();
Ogre::TexturePtr redTexture = createRedTexture("myRedTexture", 4096, 4096);
setupTileMesh(app2.getRoot()->getSceneManager("SceneManager2"), "FogOfWar.mesh", freshTexture);
app2.getRoot()->startRendering();
app2.closeApp();
return 0;
}