bool ProceduralTexture::Load(const char* fileName, class AssetCache* cache) { mWidth = 600; mHeight = 450; channels = 3; int octaves = 8; image = new unsigned char[mWidth*mHeight*channels]; PerlinNoise pnoise; int kk = 0; for (int y=0; y < mHeight; y++) { for (int x=0; x < mWidth; x++) { double pn = 0.0f; double x_f = double(x) / mWidth; double y_f = double(y) / mHeight; for (int o=0; o < octaves; ++o) { float add = pnoise.Noise(4*x_f * (1 << o), 4*y_f * (1 << o), 0.8 * ( 1 << o)); if ( add > 0) { add = -1*add + 1.0f; } else { add += 1.0f; } pn += ( add / (1 << o)); } unsigned char color = (unsigned char) (floor(255 * pn)); for (int c=0; c < channels; c++) { image[kk++] = color; } } } int mode = GL_RGB; // Generate a GL texture glGenTextures(1, &mTextureID); glBindTexture(GL_TEXTURE_2D, mTextureID); glTexImage2D(GL_TEXTURE_2D, 0, mode, mWidth, mHeight, 0, mode, GL_UNSIGNED_BYTE, image); // Use linear filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Generate mip maps, just in case glGenerateMipmap(GL_TEXTURE_2D); return true; }
GridSystem::GridSystem(int w, int h, PerlinNoise p, float gridsize) { this->selectedi = -1; this->selectedj = -1; this->w = w; this->h = h; this->offset = gridsize; this->p = p; float persistance = 0.2f; float amplitude = 1.0f; float octave = 7.0f; //initialize grids for (float i = 0.0f; i < w + (offset/2); i += offset) //float correction that's why we add (offset/2) { vector<Grid*> gridRow; for (float j = 0.0; j < h + (offset/2); j += offset) { Grid* g = new Grid(i, 0.0f, j); float val = p.Noise(i, 0.0f, j, persistance, amplitude, octave) * 3; g->assignNoise(val); /*if (i == 0.0f || (i + (2 * offset))>w || j == offset || (j + (2 * offset))>h) { g.assignNoise(p.octave_noise(i, 0.0f, j, persistance, amplitude, octave)); } else { g.assignNoise(p.octave_noise(i, 0.0f, j, persistance, amplitude, octave) * 3); }*/ gridRow.push_back(g); } grids.push_back(gridRow); } for (int i = 0; i < grids.size(); i++) { for (int j = 0; j < grids[0].size(); j++) { Grid* n_up = (i > 0) ? grids[i - 1][j] : grids[i][j]; Grid* n_down = (i < grids.size()-1) ? grids[i + 1][j] : grids[i][j]; Grid* n_right = (j < grids[0].size() - 1) ? grids[i][j + 1] : grids[i][j]; Grid* n_left = (j > 0) ? grids[i][j - 1] : grids[i][j]; grids[i][j]->setNeighboringGrid(n_up, n_right, n_down, n_left); } } /*for (int a = 0; a < grids.size()*grids[0].size()*5; a++){ int i = rand() % grids.size(); int j = rand() % grids[0].size(); grids[i][j].naturalizeGrid(); }*/ }
//....................................................................................... unsigned char *TextureGenerator::GenPerlinNoise(GLenum *_type, int *_w, int *_h, int *_d) { (*_w) = m_x; (*_h) = m_y; (*_d) = m_z; Logw("TextureGenerator::GenPerlinNoise(): Generating noise (%dx%dx%d px)\n", (*_w), (*_h), (*_d)); int offset = 0; __int64 t0 = StartCounter(); PerlinNoise *pn = NULL; // seed engine for new permutation? if (m_iPerlinSeed) pn = new PerlinNoise(m_iPerlinSeed); // use standard permutation vector G else pn = new PerlinNoise(); unsigned char *textureData = NULL; double *noiseData = NULL; double dmin = 0.0, dmax = 0.0; // GL_TEXTURE_1D|2D|3D ? switch (*_type) { case GL_TEXTURE_1D: textureData = new unsigned char[m_x * m_iBPP]; #pragma omp parallel for for (int x = 0; x < m_x; x++) { int offset = m_x * m_iBPP; double xp = (double)x / (double)m_x; double noise = pn->Noise(m_iPerlinAmp * xp, 0, 0); int c = floor(xp * 256); textureData[offset + 0] = c; textureData[offset + 1] = c; textureData[offset + 2] = c; } break; case GL_TEXTURE_2D: textureData = new unsigned char[m_x * m_y * m_iBPP]; noiseData = new double[m_x * m_y]; switch (m_ePerlinType) { case PerlinNoiseType::Simple: #pragma omp parallel for for (int y = 0; y < m_y; y++) { for (int x = 0; x < m_x; x++) { double xp = (double)x / (double)m_x; double yp = (double)y / (double)m_y; double noise = pn->Noise(m_iPerlinAmp * xp, m_iPerlinAmp * yp, 0.0); dmin = MIN(dmin, noise); dmax = MAX(dmax, noise); int offset = (y * m_x + x); noiseData[offset] = noise; } } break; case PerlinNoiseType::FractalSum: #pragma omp parallel for for (int y = 0; y < m_y; y++) { for (int x = 0; x < m_x; x++) { double xp = (double)x / (double)m_x; double yp = (double)y / (double)m_y; double noise = 0.0; for (int n = 1; n < (1 << m_nPerlinOctaves); n *= 2) noise += (1.0 / (double)n) * pn->Noise(m_iPerlinAmp * n * xp, m_iPerlinAmp * n * yp, 0.0); dmin = MIN(dmin, noise); dmax = MAX(dmax, noise); int offset = (y * m_x + x); noiseData[offset] = noise; } } break; case PerlinNoiseType::Wood: #pragma omp parallel for for (int y = 0; y < m_y; y++) { for (int x = 0; x < m_x; x++) { double xp = (double)x / (double)m_x; double yp = (double)y / (double)m_y; double noise = m_iPerlinThickness * pn->Noise(m_iPerlinAmp * xp, m_iPerlinAmp * yp, 0.0); noise -= floor(noise); dmin = MIN(dmin, noise); dmax = MAX(dmax, noise); int offset = (y * m_x + x); noiseData[offset] = noise; } } break; } // end switch PerlinNoiseType #pragma omp parallel for for (int y = 0; y < m_y; y++) { for (int x = 0; x < m_x; x++) { int offset = y * m_x + x; int offset_bpp = offset * m_iBPP; int color = (int)(((noiseData[offset] - dmin) / (dmax - dmin)) * 255.0); textureData[offset_bpp + 0] = color; textureData[offset_bpp + 1] = color; textureData[offset_bpp + 2] = color; } } break; // end GL_TEXTURE_2D case GL_TEXTURE_3D: break; } // release temp noise data if (noiseData) delete noiseData; // release pn class if (pn) delete pn; // done return (textureData); }