1 #include "pch.h"
2 #include "../common/RenderConst.h"
3 #include "../common/Def_Str.h"
4 #include "../common/data/SceneXml.h"
5 #include "../common/CScene.h"
6 #include "../../vdrift/pathmanager.h"
7 #ifdef SR_EDITOR
8 #include "../../editor/CApp.h"
9 #else
10 #include "../CGame.h"
11 #endif
12 #include <OgreRoot.h>
13 #include <OgreTimer.h>
14 #include <OgreTerrain.h>
15 #include <OgreCamera.h>
16 #include <OgreHardwarePixelBuffer.h>
17 #include <OgreRectangle2D.h>
18 #include <OgreViewport.h>
19 #include <OgreSceneNode.h>
20 #include <OgreTextureManager.h>
21 #include <OgreRenderTexture.h>
22 #include "../../shiny/Main/Factory.hpp"
23 #include "../../paged-geom/GrassLoader.h"
24 using namespace Ogre;
25
26
27 // common rtt setup
Setup(Root * rt,String sName,TexturePtr pTex,String sMtr)28 void CScene::RenderToTex::Setup(Root* rt, String sName, TexturePtr pTex, String sMtr)
29 {
30 if (!scm) scm = rt->createSceneManager(ST_GENERIC); // once-
31 // destroy old
32 if (cam) scm->destroyCamera(cam);
33 if (nd) scm->destroySceneNode(nd);
34 delete rect;
35
36 cam = scm->createCamera(sName+"C");
37 cam->setPosition(Vector3(0,10,0)); cam->setOrientation(Quaternion(0.5,-0.5,0.5,0.5));
38 cam->setNearClipDistance(0.5f); cam->setFarClipDistance(500.f);
39 cam->setAspectRatio(1.f); cam->setProjectionType(PT_ORTHOGRAPHIC);
40 cam->setOrthoWindow(1.f,1.f);
41
42 rnd = pTex->getBuffer()->getRenderTarget();
43 rnd->setAutoUpdated(false); //rnd->addListener(this);
44 vp = rnd->addViewport(cam);
45 vp->setClearEveryFrame(true); vp->setBackgroundColour(ColourValue(0,0,0,0));
46 vp->setOverlaysEnabled(false); vp->setSkiesEnabled(false);
47 vp->setShadowsEnabled(false); //vp->setVisibilityMask();
48 vp->setMaterialScheme("reflection");
49
50 rect = new Rectangle2D(true); rect->setCorners(-1,1,1,-1);
51 AxisAlignedBox aab; aab.setInfinite();
52 rect->setBoundingBox(aab); rect->setCastShadows(false);
53 rect->setMaterial( sMtr );
54
55 nd = scm->getRootSceneNode()->createChildSceneNode(sName+"N");
56 nd->attachObject(rect);
57 }
58
59 /// blendmap setup
60 // every time terrain hmap size changes
61 //----------------------------------------------------------------------------------------------------
62 const String CScene::sHmap = "HmapTex",
63 CScene::sAng = "AnglesRTT", CScene::sBlend = "blendmapRTT",
64 CScene::sAngMat = "anglesMat", CScene::sBlendMat = "blendMat",
65 CScene::sGrassDens = "GrassDensRTT", CScene::sGrassDensMat = "grassDensMat";
66
CreateBlendTex()67 void CScene::CreateBlendTex()
68 {
69 uint size = sc->td.iTerSize-1;
70 TextureManager& texMgr = TextureManager::getSingleton();
71 texMgr.remove(sHmap); texMgr.remove(sAng);
72 texMgr.remove(sBlend); texMgr.remove(sGrassDens);
73
74 // Hmap tex
75 heightTex = texMgr.createManual( sHmap, rgDef, TEX_TYPE_2D,
76 size, size, 0, PF_FLOAT32_R, TU_DYNAMIC_WRITE_ONLY); //TU_STATIC_WRITE_ONLY?
77 if (heightTex.isNull())
78 LogO("Error: Can't create Float32 (HMap) texture!");
79
80 // Angles rtt
81 angleRTex = texMgr.createManual( sAng, rgDef, TEX_TYPE_2D,
82 size, size, 0, PF_FLOAT32_R, TU_RENDERTARGET);
83 if (angleRTex.isNull())
84 LogO("Error: Can't create Float32 (Angles) RenderTarget!");
85
86 // Blendmap rtt
87 blendRTex = texMgr.createManual( sBlend, rgDef, TEX_TYPE_2D,
88 size, size, 0, PF_R8G8B8A8, TU_RENDERTARGET);
89 if (blendRTex.isNull())
90 LogO("Error: Can't create RGBA (Blendmap) RenderTarget!");
91
92 // rtt copy (not needed)
93 //blMap = texMgr.createManual("blendmapT", rgDef, TEX_TYPE_2D,
94 // size, size, 0, PF_R8G8B8A8, TU_DEFAULT);
95
96 // Grass Density rtt
97 grassDensRTex = texMgr.createManual( sGrassDens, rgDef, TEX_TYPE_2D,
98 size, size, 0, PF_R8G8B8A8, TU_RENDERTARGET);
99 if (grassDensRTex.isNull())
100 LogO("Error: Can't create RGBA (GrassDens) RenderTarget!");
101
102 blendRTT.Setup(app->mRoot, "bl", blendRTex, sBlendMat);
103 angleRTT.Setup(app->mRoot, "ang", angleRTex, sAngMat);
104 grassDensRTT.Setup(app->mRoot, "grd", grassDensRTex, sGrassDensMat);
105
106 //UpdBlendmap(); //
107 }
108
109
110 /// update, fill hmap texture from cpu floats
111 // every terrain hmap edit
112 //--------------------------------------------------------------------------
UpdBlendmap()113 void CScene::UpdBlendmap()
114 {
115 //if (!terrain) return;
116 Ogre::Timer ti;
117
118 size_t size = sc->td.iTerSize-1; //!^ same as in create
119 float* fHmap = terrain ? terrain->getHeightData() : sc->td.hfHeight;
120 if (!fHmap) return;
121
122 // fill hmap (copy to tex, full is fast)
123 HardwarePixelBufferSharedPtr pt = heightTex->getBuffer();
124 pt->lock(HardwareBuffer::HBL_DISCARD);
125
126 const PixelBox& pb = pt->getCurrentLock();
127 float* pD = static_cast<float*>(pb.data);
128 size_t aD = pb.getRowSkip() * PixelUtil::getNumElemBytes(pb.format);
129
130 register size_t j,i,a=0;
131 for (j = 0; j < size; ++j)
132 {
133 for (i = 0; i < size; ++i)
134 {
135 *pD++ = fHmap[a++];
136 }
137 pD += aD; a++; //Hmap is size+1
138 }
139 pt->unlock();
140
141 // rtt
142 if (angleRTT.rnd && blendRTT.rnd)
143 {
144 UpdLayerPars();
145
146 angleRTT.rnd->update();
147 blendRTT.rnd->update();
148
149 // copy from rtt to normal texture
150 //HardwarePixelBufferSharedPtr b = blendRTT.rnd->getBuffer();
151 //b->blit(pt);
152
153 // test save
154 //Image im;
155 //heightTex->convertToImage(im);
156 //im.save(PATHMANAGER::DataUser()+ "/../hmap.png");
157
158 //angleRTT.rnd->writeContentsToFile(PATHMANAGER::DataUser()+ "/../angle.png");
159 //blendRTT.rnd->writeContentsToFile(PATHMANAGER::DataUser()+ "/../blend.jpg");
160 }
161 else
162 LogO("Error: Didn't update blendmap !");
163
164 //LogO(String("::: Time Upd blendmap: ") + fToStr(ti.getMilliseconds(),0,1) + " ms"); // 1ms on 512, 4ms on 1k
165 }
166
167
168 /// for game, wheel contacts
169 //--------------------------------------------------------------------------
170 #ifndef SR_EDITOR
GetTerMtrIds()171 void App::GetTerMtrIds()
172 {
173 //Ogre::Timer ti;
174
175 size_t size = scn->sc->td.iTerSize-1; //!^ same as in create
176 size_t size2 = size*size;
177 // new
178 delete[] blendMtr;
179 blendMtr = new char[size2];
180 memset(blendMtr,0,size2); // zero
181
182 if (!scn->terrain) return;
183 blendMapSize = size;
184 uint8* pd = new uint8[size2*4]; // temp
185
186 HardwarePixelBufferSharedPtr pt = scn->blendRTex->getBuffer();
187 PixelBox pb(pt->getWidth(), pt->getHeight(), pt->getDepth(), pt->getFormat(), pd);
188 assert(pt->getWidth() == size && pt->getHeight() == size);
189
190 pt->blitToMemory(pb);
191 //RenderTexture* pTex = pt->getRenderTarget();
192 //pTex->copyContentsToMemory(pb, RenderTarget::FB_AUTO);
193
194 register size_t aa = pb.getRowSkip() * PixelUtil::getNumElemBytes(pb.format);
195 register uint8* p = pd, v, h;
196 register size_t j,i,a=0;
197 register char mtr;
198 for (j = 0; j < size; ++j)
199 {
200 for (i = 0; i < size; ++i)
201 {
202 mtr = 0; h = 0; // layers B,G,R,A
203 v = *p++; if (v > h) { h = v; mtr = 2; }
204 v = *p++; if (v > h) { h = v; mtr = 1; }
205 v = *p++; if (v > h) { h = v; mtr = 0; }
206 v = *p++; if (v > h) { h = v; mtr = 3; }
207 blendMtr[a++] = mtr;
208 }
209 pd += aa;
210 }
211 delete[] pd;
212
213 //LogO(String("::: Time Ter Ids: ") + fToStr(ti.getMilliseconds(),3,5) + " ms"); // 10ms on 1k
214 }
215 #endif
216
217
218 /// update blendmap layer params in shader
219 //--------------------------------------------------------------------------
UpdLayerPars()220 void CScene::UpdLayerPars()
221 {
222 // angles
223 sh::MaterialInstance* mat = sh::Factory::getInstance().getMaterialInstance(sAngMat);
224 mat->setProperty("InvTerSize", sh::makeProperty<sh::FloatValue>(new sh::FloatValue( 1.f / float(sc->td.iTerSize) )));
225 mat->setProperty("TriSize", sh::makeProperty<sh::FloatValue>(new sh::FloatValue( 2.f * sc->td.fTriangleSize )));
226
227 // blendmap
228 mat = sh::Factory::getInstance().getMaterialInstance(sBlendMat);
229 int i;
230 float Hmin[4],Hmax[4],Hsmt[4], Amin[4],Amax[4],Asmt[4];
231 float Nnext[4],Nprev[3],Nnext2[2], Nonly[4];
232 float Nfreq[3],Noct[3],Npers[3],Npow[3];
233 float Nfreq2[2],Noct2[2],Npers2[2],Npow2[2];
234 // zero
235 for (i=0; i < 4; ++i)
236 { Hmin[i]=0.f; Hmax[i]=0.f; Hsmt[i]=0.f; Amin[i]=0.f; Amax[i]=0.f; Asmt[i]=0.f;
237 Nnext[i]=0.f; Nonly[i]=0.f; }
238 for (i=0; i < 3; ++i)
239 { Nprev[i]=0.f; Nfreq[i]=0.f; Noct[i]=0.f; Npers[i]=0.f; Npow[i]=0.f; }
240 for (i=0; i < 2; ++i)
241 { Nnext2[i]=0.f; Nfreq2[i]=0.f; Noct2[i]=0.f; Npers2[i]=0.f; Npow2[i]=0.f; }
242
243 int nl = std::min(4, (int)sc->td.layers.size());
244 for (i=0; i < nl; ++i)
245 { // range
246 const TerLayer& l = sc->td.layersAll[sc->td.layers[i]];
247 Hmin[i] = l.hMin; Hmax[i] = l.hMax; Hsmt[i] = l.hSm;
248 Amin[i] = l.angMin; Amax[i] = l.angMax; Asmt[i] = l.angSm;
249 // noise
250 Nonly[i] = !l.nOnly ? 1.f : 0.f;
251 Nnext[i] = i < nl-1 ? l.noise : 0.f; // dont +1 last
252 if (i > 0) Nprev[i-1] = l.nprev; // dont -1 first
253 if (i < 2) Nnext2[i] = nl > 2 ? l.nnext2 : 0.f;
254 // n par +1,-1, +2
255 if (i < nl-1){ Nfreq[i] = l.nFreq[0]; Noct[i] = l.nOct[0]; Npers[i] = l.nPers[0]; Npow[i] = l.nPow[0]; }
256 if (i < nl-2){ Nfreq2[i]= l.nFreq[1]; Noct2[i]= l.nOct[1]; Npers2[i]= l.nPers[1]; Npow2[i]= l.nPow[1]; }
257 }
258 #define Set4(s,v) mat->setProperty(s, sh::makeProperty<sh::Vector4>(new sh::Vector4(v[0], v[1], v[2], v[3])))
259 #define Set3(s,v) mat->setProperty(s, sh::makeProperty<sh::Vector3>(new sh::Vector3(v[0], v[1], v[2])))
260 #define Set2(s,v) mat->setProperty(s, sh::makeProperty<sh::Vector2>(new sh::Vector2(v[0], v[1])))
261 #define Set1(s,v) mat->setProperty(s, sh::makeProperty<sh::FloatValue>(new sh::FloatValue(v)))
262 Set4("Hmin", Hmin); Set4("Hmax", Hmax); Set4("Hsmt", Hsmt);
263 Set4("Amin", Amin); Set4("Amax", Amax); Set4("Asmt", Asmt); Set4("Nonly", Nonly);
264 Set3("Nnext", Nnext); Set3("Nprev", Nprev); Set2("Nnext2", Nnext2);
265 Set3("Nfreq", Nfreq); Set3("Noct", Noct); Set3("Npers", Npers); Set3("Npow", Npow);
266 Set2("Nfreq2", Nfreq2); Set2("Noct2", Noct2); Set2("Npers2", Npers2); Set2("Npow2", Npow2);
267 }
268
269
270 /// update grass density channel params in shader
271 //--------------------------------------------------------------------------
UpdGrassDens()272 void CScene::UpdGrassDens()
273 {
274 if (!grassDensRTT.rnd) return;
275
276 Ogre::Timer ti;
277
278 UpdGrassPars();
279
280 grassDensRTT.rnd->update();
281
282 //grassDensRTT.rnd->writeContentsToFile(PATHMANAGER::DataUser()+"/grassRD.png");
283
284 LogO(String("::: Time Grass Dens: ") + fToStr(ti.getMilliseconds(),0,1) + " ms");
285 }
286
UpdGrassPars()287 void CScene::UpdGrassPars()
288 {
289 sh::MaterialInstance* mat = sh::Factory::getInstance().getMaterialInstance(sGrassDensMat);
290
291 float Hmin[4],Hmax[4],Hsmt[4], Amin[4],Amax[4],Asmt[4];
292 float Nmul[4], Nfreq[4],Noct[4],Npers[4],Npow[4], Rpow[4];
293
294 for (int i=0; i < 4; ++i)
295 { // range
296 const SGrassChannel& gr = sc->grChan[i];
297 Hmin[i] = gr.hMin; Hmax[i] = gr.hMax; Hsmt[i] = gr.hSm;
298 Amin[i] = gr.angMin; Amax[i] = gr.angMax; Asmt[i] = gr.angSm;
299 Rpow[i] = powf(2.f, gr.rdPow);
300 // noise
301 Nmul[i] = gr.noise; Nfreq[i] = gr.nFreq;
302 Noct[i] = gr.nOct; Npers[i] = gr.nPers; Npow[i] = gr.nPow;
303 }
304 Set4("Hmin", Hmin); Set4("Hmax", Hmax); Set4("Hsmt", Hsmt);
305 Set4("Amin", Amin); Set4("Amax", Amax); Set4("Asmt", Asmt);
306 Set4("Nmul", Nmul); Set4("Nfreq", Nfreq); Set4("Rpow", Rpow);
307 Set4("Noct", Noct); Set4("Npers", Npers); Set4("Npow", Npow);
308 }
309