1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4 (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2000-2014 Torus Knot Software Ltd
8 Also see acknowledgements in Readme.html
9 
10 You may use this sample code for anything you like, it is not covered by the
11 same license as the rest of the engine.
12 -----------------------------------------------------------------------------
13 */
14 #include "SdkSample.h"
15 #include "SamplePlugin.h"
16 
17 using namespace Ogre;
18 using namespace OgreBites;
19 
20 static SamplePlugin* sp;
21 static Sample* s;
22 
23 class _OgreSampleClassExport Sample_AtomicCounters : public SdkSample
24 {
25     Entity* mOgreEnt;
26 
27     TexturePtr mImage;
28     HardwarePixelBufferSharedPtr mPixelBuffer;
29 
30     //HardwareCounterBufferSharedPtr mBuffer;
31 
32  public:
33 
Sample_AtomicCounters()34     Sample_AtomicCounters()
35     {
36         mInfo["Title"] = "Atomic Counters";
37         mInfo["Description"] = "An example of using atomic counters to visualise GPU rasterization order";
38         mInfo["Thumbnail"] = "thumb_atomicc.png";
39         mInfo["Category"] = "Unsorted";
40     }
41 
testCapabilities(const RenderSystemCapabilities * caps)42     void testCapabilities(const RenderSystemCapabilities* caps)
43     {
44         OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
45                     "Sample currently under construction.  Try again soon!",
46                     "Sample_Compute::testCapabilities");
47 
48         if (!caps->hasCapability(RSC_ATOMIC_COUNTERS))
49         {
50             OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your render system / hardware does not support atomic counters, "
51                         "so you cannot run this sample. Sorry!",
52                         "Sample_Compute::testCapabilities");
53         }
54         else if (!caps->hasCapability(RSC_COMPUTE_PROGRAM))
55         {
56             OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your render system / hardware does not support compute programs, "
57                         "so you cannot run this sample. Sorry!",
58                         "Sample_Compute::testCapabilities");
59         }
60         else if (!caps->hasCapability(RSC_TESSELLATION_HULL_PROGRAM) || !caps->hasCapability(RSC_TESSELLATION_DOMAIN_PROGRAM))
61         {
62             OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your render system / hardware does not support tesselation programs, "
63                         "so you cannot run this sample. Sorry!",
64                         "Sample_Compute::testCapabilities");
65         }
66         else if (!caps->hasCapability(RSC_GEOMETRY_PROGRAM))
67         {
68             OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your render system / hardware does not support geometry programs, "
69                         "so you cannot run this sample. Sorry!",
70                         "Sample_Compute::testCapabilities");
71         }
72     }
73 
74     // Just override the mandatory create scene method
setupContent(void)75     void setupContent(void)
76     {
77         mCameraNode->setPosition(0, 0, -40);
78         mCamera->lookAt(0,0,0);
79         // mCamera->setNearClipDistance(0.1);
80         // mCamera->setFarClipDistance(100);
81 
82         mOgreEnt = mSceneMgr->createEntity("PlainHead", "ogrehead.mesh");
83         mOgreEnt->setMaterialName("AtomicCounters");
84         //mOgreEnt->setMaterialName("BaseWhiteNoLighting");
85         SceneNode* ogre = mSceneMgr->getRootSceneNode()->createChildSceneNode();
86         ogre->setPosition(50, -50, 140);
87         ogre->setDirection(0,0,1);
88         ogre->attachObject(mOgreEnt);
89 
90         ////////////////////////////////
91         // Image Load/Store
92         ////////////////////////////////
93 
94         mImage = TextureManager::getSingleton().createManual(
95             "ImageData", // Name of texture
96             "General",   // Name of resource group in which the texture should be created
97             TEX_TYPE_2D, // Texture type
98             256, 256, 1, // Width, Height, Depth
99             0,           // Number of mipmaps
100             PF_X8R8G8B8  // Pixel format  //TODO support formats from GL3+
101             //TU_DYNAMIC   // usage
102         );
103 
104         mImage->createShaderAccessPoint(0);
105 
106         mPixelBuffer = mImage->getBuffer(0,0);
107 
108         // Lock the buffer so we can write to it.
109         mPixelBuffer->lock(HardwareBuffer::HBL_DISCARD);
110         const PixelBox &pb = mPixelBuffer->getCurrentLock();
111 
112         // Update the contents of pb here
113         // Image data starts at pb.data and has format pb.format
114         // Here we assume data.format is PF_X8R8G8B8 so we can address pixels as uint32.
115         uint *data = reinterpret_cast<uint*>(pb.data);
116         size_t height = pb.getHeight();
117         size_t width = pb.getWidth();
118         size_t pitch = pb.rowPitch; // Skip between rows of image
119         for (size_t y = 0; y < height; ++y)
120         {
121             for(size_t x = 0; x < width; ++x)
122             {
123                 // 0xXXRRGGBB -> fill the buffer with yellow pixels
124                 // data[pitch * y + x] = 0x00FFFF00;
125                 data[pitch * y + x] = 0x0087CEEB;
126             }
127         }
128 
129         // Unlock the buffer again (frees it for use by the GPU)
130         mPixelBuffer->unlock();
131     }
132 
cleanupContent()133     void cleanupContent()
134     {
135         // Read image load/store data.
136 //        mPixelBuffer->lock(HardwareBuffer::HBL_READ_ONLY);
137 //        const PixelBox &pb = mPixelBuffer->getCurrentLock();
138 //        uint *data = static_cast<uint*>(pb.data);
139 //        size_t height = pb.getHeight();
140 //        size_t width = pb.getWidth();
141 //        size_t pitch = pb.rowPitch; // Skip between rows of image
142 //        printf("Buffer values.\n");
143 //         for (size_t y = 0; y < height; ++y)
144 //         {
145 //             for(size_t x = 0; x < width; ++x)
146 //             {
147 //                 std::cout << " " << std::hex << data[pitch * y + x];
148 //             }
149 //             std::cout << std::endl;
150 //         }
151 //        std::cout << std::hex << data[0];
152 //        std::cout << " " << data[1] << std::endl;
153 //        mPixelBuffer->unlock();
154 
155         //MeshManager::getSingleton().remove(mTetrahedraMesh->getName());
156     }
157 
frameRenderingQueued(const FrameEvent & evt)158     bool frameRenderingQueued(const FrameEvent& evt)
159     {
160         Real seconds = (Real)(Root::getSingleton().getTimer()->getMilliseconds()) / 1000.0;
161         Pass* renderPass = mOgreEnt->getSubEntity(0)->getMaterial()->getTechnique(0)->getPass(0);
162         if (renderPass->hasFragmentProgram())
163         {
164             Ogre::GpuProgramParametersSharedPtr pParams = renderPass->getFragmentProgramParameters();
165             if ( pParams.isNull() )
166             {
167                 //printf("SAD PANDA!");
168             }
169             else
170             {
171                 if ( pParams->_findNamedConstantDefinition( "ColourMe[0]" ) )
172                 {
173                     Vector4 constParam = Ogre::Vector4(0.5, 0.1, 0.0, 1.0);
174                     renderPass->getFragmentProgramParameters()->setNamedConstant("ColourMe[0]", constParam);
175 
176                     Vector4 timeParam = Ogre::Vector4(
177                         Ogre::Math::Sin(seconds)*0.5, 0.0, Ogre::Math::Cos(seconds)*0.5, 0.0);
178                     renderPass->getFragmentProgramParameters()->setNamedConstant("ColourMe[1]", timeParam);
179                 }
180                 const Ogre::GpuConstantDefinition* atom_counter_def;
181                 if ( (atom_counter_def = &pParams->getConstantDefinition("atom_counter")) )
182                 {
183                     //TODO lock buffer, retrieve counter value similar to compute above
184                     //const uint* counter = pParams->getUnsignedIntPointer(atom_counter_def->physicalIndex);
185                     //const uint* counter2 = ;
186                     //std::cout << "FOUND THE ATOMS: " << *counter << " " << std::endl; //<< *counter2 << std::endl;
187                 }
188             }
189         }
190 
191         // renderPass->getFragmentProgramParameters()->getConstantDefinition("atom_counter").getValue();
192         return SdkSample::frameRenderingQueued(evt);
193     }
194 };
195