void GPUTileStorage::init(int tileSize, int nTiles, TextureInternalFormat internalf, TextureFormat f, PixelType t, const Texture::Parameters ¶ms, bool useTileMap) { TileStorage::init(tileSize, nTiles); int maxLayers = Texture2DArray::getMaxLayers(); int nTextures = nTiles / maxLayers + (nTiles % maxLayers == 0 ? 0 : 1); needMipmaps = false; for (int i = 0; i < nTextures; ++i) { int nLayers = i == nTextures - 1 && nTiles % maxLayers != 0 ? nTiles % maxLayers : maxLayers; ptr<Texture2DArray> tex = new Texture2DArray(tileSize, tileSize, nLayers, internalf, f, t, params, Buffer::Parameters(), CPUBuffer()); needMipmaps = needMipmaps || (tex->hasMipmaps()); textures.push_back(tex); tex->generateMipMap(); for (int j = 0; j < nLayers; ++j) { freeSlots.push_back(new GPUSlot(this, i, textures[i], j)); } } if (needMipmaps) { assert(nTextures <= 8); dirtySlots = new set<GPUSlot*>[nTextures]; fbo = new FrameBuffer(); fbo->setReadBuffer(BufferId(0)); fbo->setDrawBuffers(BufferId(COLOR0 | COLOR1)); mipmapProg = new Program(new Module(330, mipmapShader)); ptr<Sampler> s = new Sampler(Sampler::Parameters().min(NEAREST).mag(NEAREST).wrapS(CLAMP_TO_EDGE).wrapT(CLAMP_TO_EDGE)); for (int i = 0; i < nTextures; ++i) { char buf[256]; sprintf(buf, "input_[%d]", i); mipmapProg->getUniformSampler(string(buf))->set(textures[i]); mipmapProg->getUniformSampler(string(buf))->setSampler(s); } mipmapParams = mipmapProg->getUniform4i("bufferLayerLevelWidth"); } else { dirtySlots = NULL; } changes = false; if (useTileMap) { assert(nTextures == 1); tileMap = new Texture2D(4096, 8, RG8, RG, UNSIGNED_BYTE, Texture::Parameters().wrapS(CLAMP_TO_EDGE).wrapT(CLAMP_TO_EDGE).min(NEAREST).mag(NEAREST), Buffer::Parameters(), CPUBuffer()); } }
Texture2DResource(ptr<ResourceManager> manager, const string &name, ptr<ResourceDescriptor> desc, const TiXmlElement *e = NULL) : ResourceTemplate<0, Texture2D>(manager, name, desc) { e = e == NULL ? desc->descriptor : e; TextureInternalFormat tf; TextureFormat f; PixelType t; Texture::Parameters params; Buffer::Parameters s; int w; int h; try { checkParameters(desc, e, "name,source,internalformat,format,type,min,mag,wraps,wrapt,minLod,maxLod,compare,borderType,borderr,borderg,borderb,bordera,maxAniso,width,height,"); getIntParameter(desc, e, "width", &w); getIntParameter(desc, e, "height", &h); getParameters(desc, e, tf, f, t); getParameters(desc, e, params); s.compressedSize(desc->getSize()); init(w, h, tf, f, t, params, s, CPUBuffer(desc->getData())); desc->clearData(); } catch (...) { desc->clearData(); throw exception(); } }
Texture3DResource(ptr<ResourceManager> manager, const string &name, ptr<ResourceDescriptor> desc, const TiXmlElement *e = NULL) : ResourceTemplate<0, Texture3D>(manager, name, desc) { e = e == NULL ? desc->descriptor : e; TextureInternalFormat tf; TextureFormat f; PixelType t; Texture::Parameters params; Buffer::Parameters s; int w; int h; int d; try { checkParameters(desc, e, "name,source,internalformat,format,type,min,mag,wraps,wrapt,wrapr,minLod,maxLod,width,height,depth,"); getIntParameter(desc, e, "width", &w); getIntParameter(desc, e, "height", &h); getIntParameter(desc, e, "depth", &d); if (h % d != 0) { if (Logger::ERROR_LOGGER != NULL) { log(Logger::ERROR_LOGGER, desc, e, "Inconsistent 'height' and 'depth' attributes"); } throw exception(); } getParameters(desc, e, tf, f, t); getParameters(desc, e, params); s.compressedSize(desc->getSize()); init(w, h / d, d, tf, f, t, params, s, CPUBuffer(desc->getData())); desc->clearData(); } catch (...) { desc->clearData(); throw exception(); } }
void EventRecorder::saveFrame(char *tga) { ptr<FrameBuffer> fb = FrameBuffer::getDefault(); vec4<GLint> vp = fb->getViewport(); int w = vp.z; int h = vp.w; char *buf = new char[w * h * 3]; fb->readPixels(0, 0, w, h, BGR, UNSIGNED_BYTE, Buffer::Parameters(), CPUBuffer(buf)); FILE *g = fopen(tga, "wb"); for (int i = 0; i < 12; ++i) { fputc(i == 2 ? 2 : 0, g); } fputc(w % 256, g); fputc(w / 256, g); fputc(h % 256, g); fputc(h / 256, g); fputc(24, g); fputc(0, g); fwrite(buf, w * h * 3, 1, g); fclose(g); delete[] buf; }
ptr<Texture2D> ParticleProducer::copyToTexture(ptr<Texture2D> t, int paramCount, getParticleParams getParams, bool useFuncRes) { int width = (int) ceil(paramCount / 4.0f); int height = getStorage()->getCapacity(); if (t == NULL || t->getWidth() != width || t->getHeight() != height) { t = new Texture2D(width, height, RGBA16F, RGBA, FLOAT, Texture::Parameters().wrapS(CLAMP_TO_BORDER).wrapT(CLAMP_TO_BORDER).min(NEAREST).mag(NEAREST), Buffer::Parameters(), CPUBuffer(NULL)); } if (params == NULL || paramSize < 4 * width * height) { if (params != NULL) { delete[] params; } params = new float[4 * width * height]; } int maxHeight = 0; vector<ParticleStorage::Particle*>::iterator i = storage->getParticles(); vector<ParticleStorage::Particle*>::iterator end = storage->end(); int h = 0; while (i != end) { ParticleStorage::Particle *p = *i++; if (useFuncRes) { h += getParams(this, p, params + 4 * width * h); } else { h = storage->getParticleIndex(p); getParams(this, p, params + 4 * width * h); ++h; } maxHeight = max(maxHeight, h); } if (maxHeight > 0) { t->setSubImage(0, 0, 0, width, maxHeight, RGBA, FLOAT, Buffer::Parameters(), CPUBuffer(params)); } return t; }
ptr<Texture2D> ParticleGrid::copyToTexture(ptr<ScreenParticleLayer> l, ptr<Texture2D> t, int &pixelsPerCell) { assert(cellSizes != NULL); pixelsPerCell = (int) ceil(float(maxParticlesPerCell) / 4.0f); int width = gridSize.x * pixelsPerCell; int height = gridSize.y; if (t == NULL || t->getWidth() != width || t->getHeight() != height) { t = new Texture2D(width, height, RGBA32F, RGBA, FLOAT, Texture::Parameters().wrapS(CLAMP_TO_BORDER).wrapT(CLAMP_TO_BORDER).min(NEAREST).mag(NEAREST), Buffer::Parameters(), CPUBuffer(NULL)); } ptr<ParticleStorage> storage = l->getOwner()->getStorage(); for (int j = 0; j < gridSize.y; ++j) { for (int i = 0; i < gridSize.x; i++) { int index = i + j * gridSize.x; int pindex = index * maxParticlesPerCell; int size = cellSizes[index]; for (int k = 0; k < size; ++k, ++pindex) { cellIndexes[pindex] = storage->getParticleIndex(l->getParticle(cellContents[pindex])); } if (size < maxParticlesPerCell) { cellIndexes[pindex] = -1; } } } t->setSubImage(0, 0, 0, width, height, RGBA, FLOAT, Buffer::Parameters(), CPUBuffer(cellIndexes)); return t; }
vec3d SceneManager::getWorldCoordinates(int x, int y) { float winx, winy, winz; ptr<FrameBuffer> fb = FrameBuffer::getDefault(); vec4<GLint> vp = fb->getViewport(); float width = (float) vp.z; float height = (float) vp.w; fb->readPixels(x, vp.w - y, 1, 1, DEPTH_COMPONENT, FLOAT, Buffer::Parameters(), CPUBuffer(&winz)); winx = (x * 2.0f) / width - 1.0f; winy = 1.0f - (y * 2.0f) / height; winz = 2.0f * winz - 1.0f; mat4d screenToWorld = getWorldToScreen().inverse(); vec4d p = screenToWorld * vec4d(winx, winy, winz, 1); return vec3d(p.x / p.w, p.y / p.w, p.z / p.w); }
Texture2DArrayResource(ptr<ResourceManager> manager, const string &name, ptr<ResourceDescriptor> desc, const TiXmlElement *e = NULL) : ResourceTemplate<0, Texture2DArray>(manager, name, desc) { e = e == NULL ? desc->descriptor : e; TextureInternalFormat tf; TextureFormat f; PixelType t; Texture::Parameters params; Buffer::Parameters s; int w; int h; int l; try { checkParameters(desc, e, "name,source,internalformat,format,type,min,mag,wraps,wrapt,minLod,maxLod,compare,borderType,borderr,borderg,borderb,bordera,maxAniso,width,height,depth,layers,"); getIntParameter(desc, e, "width", &w); getIntParameter(desc, e, "height", &h); if (e->Attribute("depth") != NULL) { getIntParameter(desc, e, "depth", &l); } else { getIntParameter(desc, e, "layers", &l); } if (h % l != 0) { if (Logger::ERROR_LOGGER != NULL) { log(Logger::ERROR_LOGGER, desc, e, "Inconsistent 'height' and 'layers' attributes"); } throw exception(); } getParameters(desc, e, tf, f, t); getParameters(desc, e, params); s.compressedSize(desc->getSize()); init(w, h / l, l, tf, f, t, params, s, CPUBuffer(desc->getData())); desc->clearData(); } catch (...) { desc->clearData(); throw exception(); } }
vec3d EditorHandler::getPosition(int x, int y) { float winx, winy, winz; ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer(); vec4<GLint> vp = fb->getViewport(); float width = (float) vp.z; float height = (float) vp.w; if (depthBuffer == NULL) { fb->readPixels(x, vp.w - y, 1, 1, DEPTH_COMPONENT, FLOAT, Buffer::Parameters(), CPUBuffer(&winz)); } else { winz = depthBuffer[x + (vp.w - y) * vp.z]; } winx = (x * 2.0f) / width - 1.0f; winy = 1.0f - (y * 2.0f) / height; winz = 2.0f * winz - 1.0f; ptr<SceneManager> manager = editors[0]->getTerrain()->getOwner(); mat4d screenToWorld = manager->getWorldToScreen().inverse(); vec4d p = screenToWorld * vec4d(winx, winy, winz, 1); double px = p.x / p.w; double py = p.y / p.w; double pz = p.z / p.w; return vec3d(px, py, pz); }
bool EditorHandler::mouseClick(button b, state s, modifier m, int x, int y) { if (editors.empty()) { return false; } if (b == LEFT_BUTTON && (m & SHIFT) != 0 && s == DOWN) { ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer(); vec4<GLint> vp = fb->getViewport(); depthBuffer = new float[vp.z * vp.w]; fb->readPixels(vp.x, vp.y, vp.z, vp.w, DEPTH_COMPONENT, FLOAT, Buffer::Parameters(), CPUBuffer(depthBuffer)); paint = true; vec3d p = getPosition(x, y); strokes.clear(); strokes.push_back(vec4d(p.x, p.y, p.z, radius)); newStrokes++; return true; } if (b == LEFT_BUTTON && s == UP && paint) { update = true; if (depthBuffer != NULL) { delete[] depthBuffer; depthBuffer = NULL; } strokes.clear(); paint = false; } return false; }
void DrawOceanTask::generateWaves() { long seed = 1234567; float min = log(lambdaMin) / log(2.0f); float max = log(lambdaMax) / log(2.0f); vec4f *waves = new vec4f[nbWaves]; sigmaXsq = 0.0; sigmaYsq = 0.0; meanHeight = 0.0; heightVariance = 0.0; amplitudeMax = 0.0; #define nbAngles 5 // impair #define angle(i) (1.5*(((i)%nbAngles)/(float)(nbAngles/2)-1)) #define dangle() (1.5/(float)(nbAngles/2)) float Wa[nbAngles]; // normalised gaussian samples int index[nbAngles]; // to hash angle order float s=0; for (int i=0; i<nbAngles; i++) { index[i]=i; float a = angle(i); // (i/(float)(nbAngle/2)-1)*1.5; s += Wa[i] = exp(-.5*a*a); } for (int i=0; i<nbAngles; i++) { Wa[i] /= s; } const float waveDispersion = 0.9f;//6; const float U0 = 10.0f; const int spectrumType = 2; for (int i = 0; i < nbWaves; ++i) { float x = i / (nbWaves - 1.0f); float lambda = pow(2.0f, (1.0f - x) * min + x * max); float ktheta = grandom(0.0f, 1.0f, &seed) * waveDispersion; float knorm = 2.0f * M_PI_F / lambda; float omega = sqrt(9.81f * knorm); float amplitude; if (spectrumType == 1) { amplitude = heightMax * grandom(0.5f, 0.15f, &seed) / (knorm * lambdaMax / (2.0f * M_PI)); } else if (spectrumType == 2) { float step = (max-min)/(nbWaves-1); // dlambda/di float omega0 = 9.81f / U0; // 100.0; if ((i%(nbAngles))==0) { // scramble angle ordre for (int k=0; k<nbAngles; k++) { // do N swap in indices int n1=lrandom(&seed)%nbAngles, n2=lrandom(&seed)%nbAngles,n; n=index[n1]; index[n1]=index[n2]; index[n2]=n; } } ktheta = waveDispersion*(angle(index[(i)%nbAngles])+.4*srnd()*dangle()); ktheta *= 1/(1+40*pow(omega0/omega,4)); amplitude = (8.1e-3*9.81*9.81) / pow(omega,5) * exp(-0.74*pow(omega0/omega,4)); amplitude *= .5*sqrt(2*3.14*9.81/lambda)*nbAngles*step; // (2/step-step/2); amplitude = 3*heightMax*sqrt(amplitude); } // cull breaking trochoids ( d(x+Acos(kx))=1-Akcos(); must be >0 ) if (amplitude > 1.0f / knorm) { amplitude = 1.0f / knorm; } else if (amplitude < -1.0f / knorm) { amplitude = -1.0f / knorm; } waves[i].x = amplitude; waves[i].y = omega; waves[i].z = knorm * cos(ktheta); waves[i].w = knorm * sin(ktheta); sigmaXsq += pow(cos(ktheta), 2.0f) * (1.0f - sqrt(1.0f - knorm * knorm * amplitude * amplitude)); sigmaYsq += pow(sin(ktheta), 2.0f) * (1.0f - sqrt(1.0f - knorm * knorm * amplitude * amplitude)); meanHeight -= knorm * amplitude * amplitude * 0.5f; heightVariance += amplitude * amplitude * (2.0f - knorm * knorm * amplitude * amplitude) * 0.25f; amplitudeMax += fabs(amplitude); } float var = 4.0f; float h0 = meanHeight - var * sqrt(heightVariance); float h1 = meanHeight + var * sqrt(heightVariance); amplitudeMax = h1 - h0; ptr<Texture1D> wavesTexture = new Texture1D(nbWaves, RGBA32F, RGBA, FLOAT, Texture::Parameters().wrapS(CLAMP_TO_BORDER).min(NEAREST).mag(NEAREST), Buffer::Parameters(), CPUBuffer(waves)); delete[] waves; nbWavesU->set(nbWaves); wavesU->set(wavesTexture); if (brdfShader != NULL) { assert(!brdfShader->getUsers().empty()); Program *prog = *(brdfShader->getUsers().begin()); prog->getUniform1f("seaRoughness")->set(sigmaXsq); prog->getUniform3f("seaColor")->set(seaColor); } }